1、目标
通过键盘上的上下左右控制角色移动,默认情况下是run,按住Shift为walk。
2、流程
(1)优化Settings代码
此时的Settings.cs完整代码如下:
using UnityEngine;public static class Settings
{// Player Movementpublic const float runningSpeed = 5.333f;public const float walkingSpeed = 2.666f;// Player Animation Parameterspublic static int xInput;public static int yInput;public static int isWalking;public static int isRunning;public static int toolEffect;public static int isUsingToolRight;public static int isUsingToolLeft;public static int isUsingToolUp;public static int isUsingToolDown;public static int isLiftingToolRight;public static int isLiftingToolLeft;public static int isLiftingToolUp;public static int isLiftingToolDown;public static int isSwingingToolRight;public static int isSwingingToolLeft;public static int isSwingingToolUp;public static int isSwingingToolDown;public static int isPickingRight;public static int isPickingLeft;public static int isPickingUp;public static int isPickingDown;// Shared Animation Parameterspublic static int idleUp;public static int idleDown;public static int idleLeft;public static int idleRight;// static constructorstatic Settings(){xInput = Animator.StringToHash("xInput");yInput = Animator.StringToHash("yInput");isWalking = Animator.StringToHash("isWalking");isRunning = Animator.StringToHash("isRunning");toolEffect = Animator.StringToHash("toolEffect");isUsingToolRight = Animator.StringToHash("isUsingToolRight");isUsingToolLeft = Animator.StringToHash("isUsingToolLeft");isUsingToolUp = Animator.StringToHash("isUsingToolUp");isUsingToolDown = Animator.StringToHash("isUsingToolDown");isLiftingToolRight = Animator.StringToHash("isLiftingToolRight");isLiftingToolLeft = Animator.StringToHash("isLiftingToolLeft");isLiftingToolUp = Animator.StringToHash("isLiftingToolUp");isLiftingToolDown = Animator.StringToHash("isLiftingToolDown");isSwingingToolRight = Animator.StringToHash("isSwingingToolRight");isSwingingToolLeft = Animator.StringToHash("isSwingingToolLeft");isSwingingToolUp = Animator.StringToHash("isSwingingToolUp");isSwingingToolDown = Animator.StringToHash("isSwingingToolDown");isPickingRight = Animator.StringToHash("isPickingRight");isPickingLeft = Animator.StringToHash("isPickingLeft");isPickingUp = Animator.StringToHash("isPickingUp");isPickingDown = Animator.StringToHash("isPickingDown");idleUp = Animator.StringToHash("idleUp");idleDown = Animator.StringToHash("idleDown");idleLeft = Animator.StringToHash("idleLeft");idleRight = Animator.StringToHash("idleRight");}}
(2)新增Direction的Enum
此时的Enum.cs完整代码如下:
public enum ToolEffect
{none, watering
}public enum Direction
{up,down,left,right,none
}
(3)给Player添加移动处理功能
给Assets -> Scripts -> Player.cs添加功能:
Player.cs的完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : SingletonMonobehaviour<Player>
{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 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>(); }private void Update(){#region Player InputResetAnimationTrigger();PlayerMovementInput();PlayerWalkInput();// 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}private void FixedUpdate(){PlayerMovement();}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("Vertical");yInput = Input.GetAxisRaw("Horizontal");// 斜着移动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;}}
}
代码解读:
1)变量定义:
输入变量(xInput, yInput)用于存储玩家的水平和垂直输入。
布尔变量(isWalking, isRunning, isIdle 等)用于表示玩家的不同状态,如行走、奔跑、空闲等。
isCarrying 表示玩家是否携带了物品。
toolEffect 枚举变量表示当前使用的工具效果。
多个布尔变量(如 isUsingToolRight, isLiftingToolLeft 等)用于表示玩家是否在使用、举起或挥动工具,以及方向。
rigidbody2D 用于处理玩家的物理移动。
playerDirection 用于记录玩家的移动方向。
movementSpeed 用于存储玩家的移动速度。
_playerInputIsDisabled 用于控制是否禁用玩家输入。
2)Awake 方法:
在对象创建时调用,用于初始化 rigidbody2D 组件。
3)Update 方法:
每帧调用,用于处理玩家的输入逻辑。
首先重置动画触发状态。
调用 PlayerMovementInput 方法处理玩家的移动输入。
调用 PlayerWalkInput 方法处理玩家是否行走的逻辑(通过Shift键控制)。
最后,调用一个事件处理器 EventHandler.CallMovementEvent,将玩家的状态信息发送给任何监听该事件的对象。
4)FixedUpdate 方法:
每固定帧调用,用于处理物理相关的移动逻辑。
调用 PlayerMovement 方法,根据输入和速度移动玩家。
5)PlayerMovement 方法:
计算玩家的移动向量,并使用 rigidbody2D.MovePosition 方法平滑地移动玩家。
6)ResetAnimationTrigger 方法:
重置所有与工具使用相关的动画触发状态。
7)PlayerMovementInput 方法:
处理玩家的移动输入,包括水平和垂直方向。
如果玩家同时按下水平和垂直键(斜向移动),则调整输入值以模拟对角线移动的速度减少。
根据输入值设置玩家的状态(奔跑、空闲),并更新玩家的移动方向。
8)PlayerWalkInput 方法:
检查玩家是否按下了Shift键,如果是,则设置玩家为行走状态,否则为奔跑状态。
整体而言,这段代码为玩家角色提供了一个基本的输入处理和移动框架,包括行走、奔跑、空闲状态的切换,以及使用工具的逻辑准备(尽管具体的工具使用逻辑未在代码中实现)。此外,通过事件系统,它还允许其他游戏组件监听玩家的状态变化。
(4)设置参照物的Sprite Renderer的属性
设置Sorting Layer为Instances,与Player保持一致。
设置Sprite Sort Point为Pivot。这样通过校验底部支点位置判断是否穿过某个物体。