Unity3D仿星露谷物语开发40之割草动画

1、目标

当Player选择Scythe后,鼠标悬浮在草上,会显示绿色光标。鼠标左击,会触发割草的动画。

2、优化Settings.cs脚本

添加以下两行代码:

// Reaping(收割)
public const int maxCollidersToTestPerReapSwing = 15; // 每次收割检测的最多的碰撞体数量
public const int maxTargetComponentsToDestroyPerReapSwing = 2; // 每次收割销毁的最多的组件数量

3、优化Player.cs脚本

1)添加一个变量:

2)Awake方法中添加新的定义

3)Start方法中添加新的定义

4)PlayerClickInput方法中增加一个if条件

5)ProcessPlayerClickInput方法增加一个case条件

6)ProcessPlayerClickInputTool方法增加case条件

7)添加判断角色方向的方法:

计算的方式如下:

private Vector3Int GetPlayerDirection(Vector3 cursorPosition, Vector3 playerPosition)
{if(cursorPosition.x > playerPosition.x&&cursorPosition.y < (playerPosition.y + cursor.ItemUseRadius / 2f)&&cursorPosition.y > (playerPosition.y - cursor.ItemUseRadius / 2f)){return Vector3Int.right;}else if(cursorPosition.x < playerPosition.x&&cursorPosition.y < (playerPosition.y + cursor.ItemUseRadius / 2f)&&cursorPosition.y > (playerPosition.y - cursor.ItemUseRadius / 2f)){return Vector3Int.left;}else if(cursorPosition.y > playerPosition.y){return Vector3Int.up;}else{return Vector3Int.down;}
}

8)添加ReapInPlayerDirectionAtCursor方法

private void ReapInPlayerDirectionAtCursor(ItemDetails itemDetails, Vector3Int playerDirection)
{StartCoroutine(ReapInPlayerDirectionAtCursorRoutine(itemDetails, playerDirection));
}

9)添加ReapInPlayerDirectionAtCursorRoutine方法

private IEnumerator ReapInPlayerDirectionAtCursorRoutine(ItemDetails itemDetails, Vector3Int playerDirection)
{PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to scythe in override animationtoolCharacterAttribute.partVariantType = PartVariantType.scythe;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);// Reap in player directionUseToolInPlayerDirection(itemDetails, playerDirection);yield return useToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;
}

10)添加UseToolInPlayerDirection方法

private void UseToolInPlayerDirection(ItemDetails equippedItemDetails, Vector3Int playerDirection)
{if (Input.GetMouseButton(0)){switch (equippedItemDetails.itemType){case ItemType.Reaping_tool:if(playerDirection == Vector3Int.right){isSwingToolRight = true;}else if(playerDirection == Vector3Int.left){isSwingToolLeft = true;}else if(playerDirection == Vector3Int.up){isSwingToolUp = true;}else if(playerDirection == Vector3Int.down){isSwingToolDown = true;}break;}// Define centre point of square which will be used for collision testing,检测碰撞的中心点位置Vector2 point = new Vector2(GetPlayerCentrePosition().x + playerDirection.x * (equippedItemDetails.itemUseRadius / 2f),GetPlayerCentrePosition().y + playerDirection.y * (equippedItemDetails.itemUseRadius / 2f));// Define size of the square which will be used for collision testingVector2 size = new Vector2(equippedItemDetails.itemUseRadius, equippedItemDetails.itemUseRadius);// Get Item components with 2D collider located in the square at the centre point defined (2d colliders tested limited to maxCollidersToTestPerReapSwing)Item[] itemArray = HelperMethods.GetComponentsAtBoxLocationNonAlloc<Item>(Settings.maxCollidersToTestPerReapSwing, point, size, 0f);int reapableItemCount = 0;// Loop through all items retrievedfor(int i = itemArray.Length - 1; i >= 0; i--){if(itemArray[i] != null){// Destory item game object if reapableif (InventoryManager.Instance.GetItemDetails(itemArray[i].ItemCode).itemType == ItemType.Reapable_scenary){// Effect positionVector3 effectPosition = new Vector3(itemArray[i].transform.position.x, itemArray[i].transform.position.y + Settings.gridCellSize / 2f,itemArray[i].transform.position.z);Destroy(itemArray[i].gameObject);reapableItemCount++;if (reapableItemCount >= Settings.maxTargetComponentsToDestroyPerReapSwing)break;}}}}
}

11)添加onEnable和onDisable方法

private void OnDisable()
{EventHandler.BeforeSceneUnloadFadeOutEvent -= DisablePlayerInputAndResetMovement;EventHandler.AfterSceneLoadFadeInEvent -= EnablePlayerInput;
}private void OnEnable()
{EventHandler.BeforeSceneUnloadFadeOutEvent += DisablePlayerInputAndResetMovement;EventHandler.AfterSceneLoadFadeInEvent += EnablePlayerInput;
}

Player.cs完整代码如下:

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;public class Player : SingletonMonobehaviour<Player>
{private WaitForSeconds afterUseToolAnimationPause;private WaitForSeconds useToolAnimationPause;private WaitForSeconds afterLiftToolAnimationPause;private WaitForSeconds liftToolAnimationPause;private bool playerToolUseDisabled = false;  // 如果玩家正在使用某个道具,其他道具将被禁用private AnimationOverrides animationOverrides;  // 动画重写控制器private GridCursor gridCursor;private Cursor cursor;private List<CharacterAttribute> characterAttributeCustomisationList;  // 目标动作列表[Tooltip("Should be populated in the prefab with the equippped item sprite renderer")][SerializeField] private SpriteRenderer equippedItemSpriteRenderer = null; // 武器的图片// Player attributes that can be swappedprivate CharacterAttribute armsCharacterAttribute;private CharacterAttribute toolCharacterAttribute;private float xInput;private float yInput;private bool isWalking;private bool isRunning;private bool isIdle;private bool isCarrying = false;private ToolEffect toolEffect = ToolEffect.none;private bool isUsingToolRight;private bool isUsingToolLeft;private bool isUsingToolUp;private bool isUsingToolDown;private bool isLiftingToolRight;private bool isLiftingToolLeft;private bool isLiftingToolUp;private bool isLiftingToolDown;private bool isPickingRight;private bool isPickingLeft;private bool isPickingUp;private bool isPickingDown;private bool isSwingToolRight;private bool isSwingToolLeft;private bool isSwingToolUp;private bool isSwingToolDown;private Camera mainCamera;private Rigidbody2D rigidbody2D;private Direction playerDirection;private float movementSpeed;private bool _playerInputIsDisabled = false;public bool PlayerInputIsDisabled { get => _playerInputIsDisabled; set => _playerInputIsDisabled = value; }protected override void Awake(){base.Awake();rigidbody2D = GetComponent<Rigidbody2D>();animationOverrides = GetComponentInChildren<AnimationOverrides>();// Initialise swappable character attributesarmsCharacterAttribute = new CharacterAttribute(CharacterPartAnimator.arms, PartVariantColour.none, PartVariantType.none);toolCharacterAttribute = new CharacterAttribute(CharacterPartAnimator.tool, PartVariantColour.none, PartVariantType.none);// Initialise character attribute listcharacterAttributeCustomisationList = new List<CharacterAttribute>();mainCamera = Camera.main;}private void OnDisable(){EventHandler.BeforeSceneUnloadFadeOutEvent -= DisablePlayerInputAndResetMovement;EventHandler.AfterSceneLoadFadeInEvent -= EnablePlayerInput;}private void OnEnable(){EventHandler.BeforeSceneUnloadFadeOutEvent += DisablePlayerInputAndResetMovement;EventHandler.AfterSceneLoadFadeInEvent += EnablePlayerInput;}private void Start(){gridCursor = FindObjectOfType<GridCursor>();cursor = FindObjectOfType<Cursor>();useToolAnimationPause = new WaitForSeconds(Settings.useToolAnimationPause);afterUseToolAnimationPause = new WaitForSeconds(Settings.afterUseToolAnimationPause);liftToolAnimationPause = new WaitForSeconds(Settings.liftToolAnimationPause);afterLiftToolAnimationPause = new WaitForSeconds(Settings.afterLiftToolAnimationPause);}private void Update(){#region  Player Inputif (!PlayerInputIsDisabled){ResetAnimationTrigger();PlayerMovementInput();PlayerWalkInput();PlayerClickInput();PlayerTestInput();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}#endregion Player Input}private void FixedUpdate(){PlayerMovement();}/// <summary>/// 展示拿东西的动画/// </summary>/// <param name="itemCode"></param>public void ShowCarriedItem(int itemCode){ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);if(itemDetails != null){equippedItemSpriteRenderer.sprite = itemDetails.itemSprite;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 1f);// Apply 'carry' character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.carry;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = true;}}public void ClearCarriedItem(){equippedItemSpriteRenderer.sprite = null;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 0f);// Apply base character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.none;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = false;}private void PlayerMovement(){Vector2 move = new Vector2(xInput * movementSpeed * Time.deltaTime, yInput * movementSpeed * Time.deltaTime);rigidbody2D.MovePosition(rigidbody2D.position + move);}private void ResetAnimationTrigger(){toolEffect = ToolEffect.none;isUsingToolRight = false;isUsingToolLeft = false;isUsingToolUp = false;isUsingToolDown = false;isLiftingToolRight = false;isLiftingToolLeft = false;isLiftingToolUp = false;isLiftingToolDown = false;isPickingRight = false;isPickingLeft = false;isPickingUp = false;isPickingDown = false;isSwingToolRight = false;isSwingToolLeft = false;isSwingToolUp = false;isSwingToolDown = false;}private void PlayerMovementInput(){xInput = Input.GetAxisRaw("Horizontal");yInput = Input.GetAxisRaw("Vertical");// 斜着移动if (xInput != 0 && yInput != 0) {xInput = xInput * 0.71f;yInput = yInput * 0.71f;}// 在移动if (xInput != 0 || yInput != 0) {isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;// Capture player direction for save gameif (xInput < 0){playerDirection = Direction.left;}else if (xInput > 0){playerDirection = Direction.right;}else if (yInput < 0){playerDirection = Direction.down;}else{playerDirection = Direction.up;}}else if(xInput == 0 && yInput == 0){isRunning = false;isWalking = false;isIdle = true;}}// 按住Shift键移动为walkprivate void PlayerWalkInput(){if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)){isRunning = false;isWalking = true;isIdle = false;movementSpeed = Settings.walkingSpeed;}else{isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;}}private void PlayerClickInput(){if (!playerToolUseDisabled){if (Input.GetMouseButton(0)){if (gridCursor.CursorIsEnabled || cursor.CursorIsEnable){// Get Cursor Grid PositionVector3Int cursorGridPosition = gridCursor.GetGridPositionForCursor();// Get Player Grid PositionVector3Int playerGridPosition = gridCursor.GetGridPositionForPlayer();ProcessPlayerClickInput(cursorGridPosition, playerGridPosition);}}}}private void ProcessPlayerClickInput(Vector3Int cursorGridPosition, Vector3Int playerGridPosition){ResetMovement();Vector3Int playerDirection = GetPlayerClickDirection(cursorGridPosition, playerGridPosition);// Get Selected item detailsItemDetails itemDetails = InventoryManager.Instance.GetSelectedInventoryItemDetails(InventoryLocation.player);// Get Grid property details at cursor position (the GridCursor validation routine ensures that grid property details are not null)GridPropertyDetails gridPropertyDetails = GridPropertiesManager.Instance.GetGridPropertyDetails(cursorGridPosition.x, cursorGridPosition.y);if(itemDetails != null){switch (itemDetails.itemType){case ItemType.Seed:if (Input.GetMouseButtonDown(0)){ProcessPlayerClickInputSeed(itemDetails);}break;case ItemType.Commodity:if (Input.GetMouseButtonDown(0)){ProcessPlayerClickInputCommodity(itemDetails);}break;case ItemType.Watering_tool:case ItemType.Hoeing_tool:case ItemType.Reaping_tool:ProcessPlayerClickInputTool(gridPropertyDetails, itemDetails, playerDirection);break;case ItemType.none:break;case ItemType.count:break;default:break;}}}private Vector3Int GetPlayerClickDirection(Vector3Int cursorGridPosition, Vector3Int playerGridPosition) {if(cursorGridPosition.x > playerGridPosition.x){return Vector3Int.right;}else if(cursorGridPosition.x < playerGridPosition.x){return Vector3Int.left;}else if(cursorGridPosition.y > playerGridPosition.y){return Vector3Int.up;}else{return Vector3Int.down;}}private Vector3Int GetPlayerDirection(Vector3 cursorPosition, Vector3 playerPosition){if(cursorPosition.x > playerPosition.x&&cursorPosition.y < (playerPosition.y + cursor.ItemUseRadius / 2f)&&cursorPosition.y > (playerPosition.y - cursor.ItemUseRadius / 2f)){return Vector3Int.right;}else if(cursorPosition.x < playerPosition.x&&cursorPosition.y < (playerPosition.y + cursor.ItemUseRadius / 2f)&&cursorPosition.y > (playerPosition.y - cursor.ItemUseRadius / 2f)){return Vector3Int.left;}else if(cursorPosition.y > playerPosition.y){return Vector3Int.up;}else{return Vector3Int.down;}}private void ProcessPlayerClickInputSeed(ItemDetails itemDetails){if(itemDetails.canBeDropped && gridCursor.CursorPositionIsValid){EventHandler.CallDropSelectedItemEvent();}}private void ProcessPlayerClickInputCommodity(ItemDetails itemDetails){if(itemDetails.canBeDropped && gridCursor.CursorPositionIsValid){EventHandler.CallDropSelectedItemEvent();}}private void ProcessPlayerClickInputTool(GridPropertyDetails gridPropertyDetails, ItemDetails itemDetails, Vector3Int playerDirection){// Switch on toolswitch (itemDetails.itemType){case ItemType.Hoeing_tool:if (gridCursor.CursorPositionIsValid){HoeGroundAtCursor(gridPropertyDetails, playerDirection);}break;case ItemType.Watering_tool:if (gridCursor.CursorPositionIsValid){WaterGroundAtCursor(gridPropertyDetails, playerDirection);}break;case ItemType.Reaping_tool:if (cursor.CursorPositionIsValid){playerDirection = GetPlayerDirection(cursor.GetWorldPositionForCursor(), GetPlayerCentrePosition());ReapInPlayerDirectionAtCursor(itemDetails, playerDirection);}break;default:break;}}private void ReapInPlayerDirectionAtCursor(ItemDetails itemDetails, Vector3Int playerDirection){StartCoroutine(ReapInPlayerDirectionAtCursorRoutine(itemDetails, playerDirection));}private IEnumerator ReapInPlayerDirectionAtCursorRoutine(ItemDetails itemDetails, Vector3Int playerDirection){PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to scythe in override animationtoolCharacterAttribute.partVariantType = PartVariantType.scythe;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);// Reap in player directionUseToolInPlayerDirection(itemDetails, playerDirection);yield return useToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}private void UseToolInPlayerDirection(ItemDetails equippedItemDetails, Vector3Int playerDirection){if (Input.GetMouseButton(0)){switch (equippedItemDetails.itemType){case ItemType.Reaping_tool:if(playerDirection == Vector3Int.right){isSwingToolRight = true;}else if(playerDirection == Vector3Int.left){isSwingToolLeft = true;}else if(playerDirection == Vector3Int.up){isSwingToolUp = true;}else if(playerDirection == Vector3Int.down){isSwingToolDown = true;}break;}// Define centre point of square which will be used for collision testing,检测碰撞的中心点位置Vector2 point = new Vector2(GetPlayerCentrePosition().x + playerDirection.x * (equippedItemDetails.itemUseRadius / 2f),GetPlayerCentrePosition().y + playerDirection.y * (equippedItemDetails.itemUseRadius / 2f));// Define size of the square which will be used for collision testingVector2 size = new Vector2(equippedItemDetails.itemUseRadius, equippedItemDetails.itemUseRadius);// Get Item components with 2D collider located in the square at the centre point defined (2d colliders tested limited to maxCollidersToTestPerReapSwing)Item[] itemArray = HelperMethods.GetComponentsAtBoxLocationNonAlloc<Item>(Settings.maxCollidersToTestPerReapSwing, point, size, 0f);int reapableItemCount = 0;// Loop through all items retrievedfor(int i = itemArray.Length - 1; i >= 0; i--){if(itemArray[i] != null){// Destory item game object if reapableif (InventoryManager.Instance.GetItemDetails(itemArray[i].ItemCode).itemType == ItemType.Reapable_scenary){// Effect positionVector3 effectPosition = new Vector3(itemArray[i].transform.position.x, itemArray[i].transform.position.y + Settings.gridCellSize / 2f,itemArray[i].transform.position.z);Destroy(itemArray[i].gameObject);reapableItemCount++;if (reapableItemCount >= Settings.maxTargetComponentsToDestroyPerReapSwing)break;}}}}}private void WaterGroundAtCursor(GridPropertyDetails gridPropertyDetails, Vector3Int playerDirection) { // Trigger animationStartCoroutine(WaterGroundAtCursorRoutine(playerDirection, gridPropertyDetails));}private IEnumerator WaterGroundAtCursorRoutine(Vector3Int playerDirection, GridPropertyDetails gridPropertyDetails) {PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to watering can in override animationtoolCharacterAttribute.partVariantType = PartVariantType.wateringCan;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);toolEffect = ToolEffect.watering;if(playerDirection == Vector3Int.right){isLiftingToolRight = true;}else if(playerDirection == Vector3Int.left){isLiftingToolLeft = true;}else if(playerDirection == Vector3Int.up){isLiftingToolUp = true;}else if(playerDirection == Vector3Int.down){isLiftingToolDown = true;}yield return liftToolAnimationPause;// Set Grid property details for watered groundif(gridPropertyDetails.daysSinceWatered == -1){gridPropertyDetails.daysSinceWatered = 0;}// Set grid property to wateredGridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// Display watered grid tilesGridPropertiesManager.Instance.DisplayWateredGround(gridPropertyDetails);// After animation pauseyield return afterLiftToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}private void HoeGroundAtCursor(GridPropertyDetails gridPropertyDetails, Vector3Int playerDirection) {// Trigger animationStartCoroutine(HoeGroundAtCursorRoutine(playerDirection, gridPropertyDetails));}private IEnumerator HoeGroundAtCursorRoutine(Vector3Int playerDirection, GridPropertyDetails gridPropertyDetails){PlayerInputIsDisabled = true;playerToolUseDisabled = true;// Set tool animation to hoe in override animationtoolCharacterAttribute.partVariantType = PartVariantType.hoe;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(toolCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);if(playerDirection == Vector3Int.right){isUsingToolRight = true;}else if(playerDirection == Vector3Int.left){isUsingToolLeft = true;}else if(playerDirection == Vector3Int.up){isUsingToolUp = true;}else if(playerDirection == Vector3Int.down){isUsingToolDown = true;}yield return useToolAnimationPause;// Set Grid property details for dug groundif(gridPropertyDetails.daysSinceDug == -1){gridPropertyDetails.daysSinceDug = 0;}// Set grid property to dugGridPropertiesManager.Instance.SetGridPropertyDetails(gridPropertyDetails.gridX, gridPropertyDetails.gridY, gridPropertyDetails);// Display dug grid tilesGridPropertiesManager.Instance.DisplayDugGround(gridPropertyDetails);// After animation pauseyield return afterUseToolAnimationPause;PlayerInputIsDisabled = false;playerToolUseDisabled = false;}public Vector3 GetPlayerViewportPosition(){// Vector3 viewport position for player (0,0) viewport bottom left, (1,1) viewport top rightreturn mainCamera.WorldToViewportPoint(gameObject.transform.position);}public Vector3 GetPlayerCentrePosition(){return new Vector3(transform.position.x, transform.position.y + Settings.playerCentreYOffset, transform.position.z);}public void DisablePlayerInputAndResetMovement(){DisablePlayerInpupt();ResetMovement();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}private void ResetMovement(){// Reset movementxInput = 0f;yInput = 0f;isRunning = false;isWalking = false;isIdle = true;}public void DisablePlayerInpupt(){PlayerInputIsDisabled = true;}public void EnablePlayerInput(){PlayerInputIsDisabled = false;}/// <summary>/// Temp routine for test input/// </summary>private void PlayerTestInput(){// Trigger Advance Timeif (Input.GetKeyDown(KeyCode.T)){TimeManager.Instance.TestAdvanceGameMinute();}// Trigger Advance Dayif (Input.GetKeyDown(KeyCode.G)){TimeManager.Instance.TestAdvanceGameDay();}// Test scene unload / loadif (Input.GetKeyDown(KeyCode.L)){SceneControllerManager.Instance.FadeAndLoadScene(SceneName.Scene1_Farm.ToString(), transform.position);}}
}

4、运行游戏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77858.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LLM】基于 Ollama 部署 DeepSeek-R1 本地大模型

本文详细介绍如何在 Linux 和 Windows 环境下,通过 Docker Compose 整合 Ollama 和 Open WebUI,部署 DeepSeek-R1 大语言模型,并提供 GPU 加速支持。无论你是开发者还是 AI 爱好者,均可通过本指南快速搭建私有化 GPT 环境。 一、环境准备 1. Docker 与 Docker Compose 安…

深度体验两年半!MAC 硬件好物分享|屏幕、挂灯、键盘、鼠标

写在前面 最近快五一放假了&#xff0c;所以写点轻松一点的文章&#xff5e; 这篇文章就介绍这两年半来&#xff0c;我一直在用MAC硬件搭子&#xff01;&#xff01;而买这些硬件设备的钱都是一行行代码写出来的!! 我的MAC是21款14寸 m1 pro 32512版本&#xff0c;22年年底在…

Python math 库教学指南

Python math 库教学指南 一、概述 math 库是 Python 标准库中用于数学运算的核心模块&#xff0c;提供以下主要功能&#xff1a; 数学常数&#xff08;如 π 和 e&#xff09;基本数学函数&#xff08;绝对值、取整等&#xff09;幂与对数运算三角函数双曲函数特殊函数&…

Mac下安装Python3,并配置环境变量设置为默认

下载Python 访问Python官方网站 https://www.python.org/ 首先获得python3安装路径 执行命令&#xff1a; which python3 以我这台电脑为例&#xff0c;路径为&#xff1a;/Library/Frameworks/Python.framework/Versions/3.9/bin/python3 编辑 bash_profile 文件 然后用 vim 打…

Arduino程序结构详解与嵌入式开发对比指南

Arduino编程详解&#xff1a;从基础到进阶实践 一、Arduino程序的核心架构与扩展设计 1.1 程序框架的深度解析 Arduino程序的基石setup()和loop()函数构成了整个开发体系的核心逻辑。这两个函数的设计哲学体现了嵌入式系统开发的两个关键维度&#xff1a; 初始化阶段&#…

5W1H分析法——AI与思维模型【86】

一、定义 5W1H分析法思维模型是一种通过对问题或事件从原因&#xff08;Why&#xff09;、对象&#xff08;What&#xff09;、地点&#xff08;Where&#xff09;、时间&#xff08;When&#xff09;、人员&#xff08;Who&#xff09;和方法&#xff08;How&#xff09;六个…

css 数字从0开始增加的动画效果

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在有些时候比如在做C端项目的时候&#xff0c;页面一般需要一些炫酷效果&#xff0c;比如数字会从小值自动加到数据返回的值 css 数字从0开始增加的动画效果 分析&#xff1a; 提示&#xff1a;这里填…

CUDA编程 - 如何使用 CUDA 流在 GPU 设备上并发执行多个内核 - 如何应用到自己的项目中 - concurrentKernels

如何使用 CUDA 流在 GPU 设备上并发执行多个内核 一、完整代码与例程目的1.1、通过现实场景来理解多任务协作&#xff1a;1.2、完整代码&#xff1a; 二、代码拆解与复用2.1、编程模版 一、完整代码与例程目的 项目地址&#xff1a;https://github.com/NVIDIA/cuda-samples/tr…

vue3 打字机效果

打字机效果 因后端返回的数据也是通过microsoft/fetch-event-source 一句一句流式返回 但是前端展示效果想要实现打字机效果 代码如下 <template><div><div class"text-container"><span class"text-content">{{ displayText }…

线上JVM调优与全栈性能优化 - Java架构师面试实战

线上JVM调优与全栈性能优化 - Java架构师面试实战 本文通过一场互联网大厂的Java架构师面试&#xff0c;深入探讨了线上JVM调优、OOM定位、死锁定位、内存和CPU调优、线程池调优、数据库调优、缓存调优、网络调优、微服务调优及分布式调优等关键领域。 第一轮提问 面试官&am…

【Android】轻松实现实时FPS功能

文章目录 实时FPS 实时FPS 初始化 choreographer Choreographer.getInstance();lastFrameTimeNanos System.nanoTime();choreographer.postFrameCallback(frameCallback);监听并显示 Choreographer.FrameCallback frameCallback new Choreographer.FrameCallback() {Overri…

GD32F407单片机开发入门(十九)DMA详解及ADC-DMA方式采集含源码

文章目录 一.概要二.GD32F407VET6单片机DMA外设特点三.GD32单片机DMA内部结构图四.DMA各通道请求五.GD32F407VET6单片机ADC-DMA采集例程六.工程源代码下载七.小结 一.概要 基本概念&#xff1a; DMA是Direct Memory Access的首字母缩写,是一种完全由硬件执行数据交换的工作方式…

vue报错:Error: Cannot find module ‘is-stream‘

此错误提示 Cannot find module ‘is-stream’ 表明 Node.js 无法找到 is-stream 模块。一般而言&#xff0c;这是由于项目中未安装该模块所导致的。 解决方案: //npm npm install is-stream //yarn yarn add is-stream安装后检查 安装完成之后&#xff0c;你可以再次运行项目…

全局事件总线EventBus的用法

全局事件总线 EventBus 在前端开发中是一种用于实现组件间通信的机制&#xff0c;适用于兄弟组件或跨层级组件间的数据传递。 1. 创建全局 EventBus 实例 在前端项目中&#xff0c;先创建一个全局的 EventBus 实例。在 Vue 中&#xff0c;可以通过创建一个新的 Vue 实例来实现…

SpringBoot 设置HTTP代理访问

SpringBoot 设置HTTP代理访问 遇到这样的一个场景&#xff0c;代码部署到私有服务器上去之后&#xff0c;这台私有服务器a无法直接访问公网&#xff0c;需要通过代理转发到另外一台专门访问公网的服务器b, 让服务器b去请求对应的公网ip&#xff0c;于是就需要设置Http代理。 …

在C# WebApi 中使用 Nacos01:基础安装教程和启动运行

一、JDK的安装 Nacos需要依赖JAVA环境运行,所以需要先安装JDK 1.检查是否安装 可用命令行检查是否安装JDK 直接win+r,cmd: java -version 出现这个说明安装成功 2.下载JDK 访问官网点击下载:

cURL 入门:10 分钟学会用命令行发 HTTP 请求

curl初识 curl 通过 URL 传输数据的命令行工具和库是一个非常强大的命令行工具&#xff0c;用于在网络上传输数据。它支持众多的协议&#xff0c;像 dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps…

Redis应用场景实战:穿透/雪崩/击穿解决方案与分布式锁深度剖析

一、缓存异常场景全解与工业级解决方案 1.1 缓存穿透&#xff1a;穿透防御的三重门 典型场景 恶意爬虫持续扫描不存在的用户ID 参数注入攻击&#xff08;如SQL注入式查询&#xff09; 业务设计缺陷导致无效查询泛滥 解决方案进化论 第一层防护&#xff1a;布隆过滤器&am…

C# 高效操作excel文件

C#高效操作Excel文件指南 一、主流Excel处理方案对比 方案类型特点适用场景​​EPPlus​​第三方库功能全面&#xff0c;性能好&#xff0c;支持.xlsx复杂Excel操作&#xff0c;大数据量​​NPOI​​第三方库支持.xls和.xlsx&#xff0c;功能全面兼容旧版Excel文件​​Closed…

Rust 学习笔记:结构体(struct)

Rust 学习笔记&#xff1a;结构体&#xff08;struct&#xff09; Rust 学习笔记&#xff1a;结构体&#xff08;struct&#xff09;结构体的定义和实例化使用字段初始化简写用 Struct Update 语法从其他实例创建实例使用没有命名字段的元组结构来创建不同的类型没有任何字段的…