ThirdPersonUserControl 代码汉化介绍
第三人称有三个代码玩家挂载后理论上可以移动,正确设置动画后就可以移动,新的人物。
using UnityEngine;//引用Unity引擎的类
#if ENABLE_INPUT_SYSTEM //进行条件编译,如果启用了Input System,则引用UnityEngine.InputSystem。
using UnityEngine.InputSystem;
#endif
/* Note: animations are called via the controller for both the character and capsule using animator null checks
*///* 注意,动画是通过控制器调用的,对角色和胶囊都使用了 animator 空值检查 */
*/
namespace StarterAssets
{
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(BasicRigidBodyPush))]
[RequireComponent(typeof(AudioSource))]
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(StarterAssetsInputs))]
#if ENABLE_INPUT_SYSTEM
[RequireComponent(typeof(PlayerInput))]
#endif
public class ThirdPersonController : MonoBehaviour
{
[Header(" ThirdPersonController")]
[Tooltip("主要功能是控制一个第三人称角色的行为,包括移动、跳跃、检测地面状态等,并与动画系统配合实现角色的各种动画效果。同时,它还支持虚拟摄像机跟随角色并根据玩家输入调整视角。这段代码通过将角色的行为和动画逻辑分离,使得角色的控制更加灵活和易于维护。")]
public GameObject Playerprefab;
[Header("Player玩家")]//标签会在Inspector中显示
[Tooltip("Move speed of the character in m/s的移动速度(m/s)")]//提示会在Inspector中显示
[Header("速度")]
public float MoveSpeed = 2.0f;
[Header("加速")]
[Tooltip("Sprint speed of the character in m/s冲刺速度,单位为m/s")]
public float SprintSpeed = 5.335f;
[Tooltip("How fast the character turns to face movement direction“角色转向面部移动方向的速度有多快”")]
[Range(0.0f, 0.3f)]
public float RotationSmoothTime = 0.12f;
[Tooltip("Acceleration and deceleration加速和减速”")]
public float SpeedChangeRate = 10.0f;
[Header("移动声")]
public AudioClip LandingAudioClip;
public AudioClip[] FootstepAudioClips;
[Range(0, 1)] public float FootstepAudioVolume = 0.5f;
[Space(10)]
[Tooltip("The height the player can jump跳跃高度")]
public float JumpHeight = 1.2f;
[Tooltip("The character uses its own gravity value. The engine default is -9.81f角色使用自己的重力值。发动机默认值为-9.81f")]
public float Gravity = -15.0f;
[Space(10)]
[Tooltip("Time required to pass before being able to jump again. Set to 0f to instantly jump again再次跳跃所需的时间。设置为0f可立即再次跳跃")]
public float JumpTimeout = 0.50f;
[Tooltip("Time required to pass before entering the fall state. Useful for walking down stairs“进入坠落状态所需的时间。对走下楼梯很有用")]
public float FallTimeout = 0.15f;
[Header("Player Grounded地面")]
[Tooltip("If the character is grounded or not. Not part of the CharacterController built in grounded check是否在地面上")]
public bool Grounded = true;
[Tooltip("Useful for rough ground垂直偏移")]
public float GroundedOffset = -0.14f;
[Tooltip("The radius of the grounded check. Should match the radius of the CharacterController接地检查的半径。应与字符控制器的半径相匹配")]
public float GroundedRadius = 0.28f;
[Tooltip("What layers the character uses as ground使用哪些层作为背景=default")]
public LayerMask GroundLayers;
[Header("Cinemachine虚拟相机")]
[Tooltip("The follow target set in the Cinemachine Virtual Camera that the camera will follow是虚拟相机将跟随的目标=Playercameraroot")]
public GameObject CinemachineCameraTarget;
[Tooltip("How far in degrees can you move the camera up上限制像机在垂直方向上的最大和最小倾斜角度。")]
public float TopClamp = 70.0f;
[Tooltip("How far in degrees can you move the camera down下限制")]
public float BottomClamp = -30.0f;
[Tooltip("Additional degress to override the camera. Useful for fine tuning camera position when locked用于调整摄像机的角度")]
public float CameraAngleOverride = 0.0f;
[Tooltip("For locking the camera position on all axis锁定摄像机位置")]
public bool LockCameraPosition = false;
[Header("私有变量(内部状态")]
[Tooltip("定义了一些内部状态变量,用于存储角色的速度、动画混合速度、目标旋转角度、垂直速度等信息。\r\nPlayerInput 是条件编译的变量,仅在启用了Input System时才存在。\r\n_terminalVelocity 是角色的终端速度,防止角色下落速度无限增加。\r\n_threshold 是一个常量,用于检测输入是否接近零。")]
// cinemachine
private float _cinemachineTargetYaw;//用于存储虚拟摄像机的目标水平旋转角度
private float _cinemachineTargetPitch;//用于存储虚拟摄像机的目标垂直旋转角度
// player
private float _speed;//当前的实际移动速度。
private float _animationBlend;//用于存储动画混合速度,这一变量帮助动画更平滑地过渡。
private float _targetRotation = 0.0f;//目标转向角度是根据玩家输入面向移动方向的角度。
private float _rotationVelocity;//用于存储角色转向的速度。
private float _verticalVelocity;//用于存储角色的垂直速度。是角色根据玩家输入面向移动方向的角度。
private float _terminalVelocity = 53.0f;//即“终端速度”,防止下落速度无限增加。
// timeout deltatime
private float _jumpTimeoutDelta;//用于存储角色在跳跃后的“跳跃超时时间”,帮助控制角色在跳跃后需要等待一段时间才能再次跳跃。
private float _fallTimeoutDelta;//用于存储角色在开始坠落后的“坠落超时时间”,这一变量有助于角色在行走下楼梯时避免立即进入坠落动画状态。
// animation IDs
private int _animIDSpeed;
private int _animIDGrounded;
private int _animIDJump;
private int _animIDFreeFall;
private int _animIDMotionSpeed;
#if ENABLE_INPUT_SYSTEM
private PlayerInput _playerInput;
#endif
private Animator _animator;
private CharacterController _controller;
private StarterAssetsInputs _input;
// private TestControlsInputs _input;
private GameObject _mainCamera;
private const float _threshold = 0.01f;
private bool _hasAnimator;
[Tooltip(" 属性IsCurrentDeviceMouse 是一个只读属性,用于判断当前输入设备是否为鼠标和键盘。当启用了Input System时,它会根据当前控制方案进行判断。")]
private bool IsCurrentDeviceMouse
{
get
{
#if ENABLE_INPUT_SYSTEM
return _playerInput.currentControlScheme == "KeyboardMouse";
#else
return false;
#endif
}
}
[tooltip(" 被实例化后立即调用,用于获取主摄像机的游戏对象引用。。")]
private void Awake()
{
// get a reference to our main camera获取对我们主摄像机的引用
if (_mainCamera == null)
{
_mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
}
}
[Tooltip(" 被实例化后立即调用,用于初始化角色的状态。第一次调用Update方法之前调用,用于初始化虚拟摄像机的目标水平旋转角度、获取Animator和CharacterController组件引用、初始化跳跃和坠落超时时间。"]
private void Start()
{
_cinemachineTargetYaw = CinemachineCameraTarget.transform.rotation.eulerAngles.y;
_hasAnimator = TryGetComponent(out _animator);
_controller = GetComponent<CharacterController>();
_input = GetComponent<StarterAssetsInputs>();
// _input =GetComponent< TestControlsInput > ();
#if ENABLE_INPUT_SYSTEM
_playerInput = GetComponent<PlayerInput>();
#else
Debug.LogError( "Starter Assets package is missing dependencies. Please use Tools/Starter Assets/Reinstall Dependencies to fix it");
#endif
AssignAnimationIDs();
// reset our timeouts on start
_jumpTimeoutDelta = JumpTimeout;
_fallTimeoutDelta = FallTimeout;
}
[Tooltip("每帧调用,用于检测角色是否在地面上、处理跳跃和重力逻辑、处理角色移动逻辑。")]
private void Update()
{
_hasAnimator = TryGetComponent(out _animator);
JumpAndGravity();
GroundedCheck();
Move();
}
[Tooltip("每帧调用,用于更新虚拟摄像机的目标旋转角度、处理动画事件。")]
private void LateUpdate()
{
CameraRotation();
}
[Tooltip("动画事件回调,动画ID分配动画参数名称转换为整数ID,以便在代码中更高效地访问这些参数。\r\n")]
private void AssignAnimationIDs()
{
_animIDSpeed = Animator.StringToHash("Speed");
_animIDGrounded = Animator.StringToHash("Grounded");
_animIDJump = Animator.StringToHash("Jump");
_animIDFreeFall = Animator.StringToHash("FreeFall");
_animIDMotionSpeed = Animator.StringToHash("MotionSpeed");
}
[Tooltip("地面检测。每帧调用 GroundedCheck() 方法,用于检查角色是否在地上。\r\n使用 Physics.CheckSphere() 方法,配合 GroundedOffset 和 GroundedRadius 检测角色是否接触地面。\r\n如果角色在地面上,并且有Animator组件,则设置 Grounded 动画参数为 true。"]
private void GroundedCheck()
{
// set sphere position, with offset设置球体位置并偏移
Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset,
transform.position.z);
Grounded = Physics.CheckSphere(spherePosition, GroundedRadius, GroundLayers,
QueryTriggerInteraction.Ignore);
// update animator if using character/ 如果使用角色则更新动画器
if (_hasAnimator)
{
_animator.SetBool(_animIDGrounded, Grounded);
}
}
[Tooltip("摄像机旋转每帧调用 CameraRotation() 方法,用于处理虚拟摄像机的旋转逻辑。\r\n如果玩家有输入并且摄像机位置没有被锁定,则根据玩家的输入更新摄像机的目标水平和垂直旋转角度。\r\n使用 ClampAngle() 方法,限制摄像机的旋转角度在合理范围内,避免摄像机旋转角度超出360度。\r\n最后,将更新后的旋转角度应用到虚拟摄像机的目标对象上。"]]
private void CameraRotation()
{
// if there is an input and camera position is not fixed如果有输入并且摄像头位置未固定
if (_input.look.sqrMagnitude >= _threshold && !LockCameraPosition)
{
//Don't multiply mouse input by Time.deltaTime;不要将鼠标输入乘以时间时间
float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime;
_cinemachineTargetYaw += _input.look.x * deltaTimeMultiplier;
_cinemachineTargetPitch += _input.look.y * deltaTimeMultiplier;
}
// clamp our rotations so our values are limited 360 degrees/ 限制我们的旋转,使我们的数值限制在 360 度以内
_cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue);
_cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp);
// Cinemachine will follow this targetCinemachine 将跟随此目标
CinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch + CameraAngleOverride,
_cinemachineTargetYaw, 0.0f);
}
[Tooltip("移动处理处理角色的移动逻辑。\r\n如果玩家没有输入,则目标速度为0。\r\n计算当前角色的水平速度,并根据目标速度进行加速或减速。\r\n使用 Mathf.SmoothDampAngle() 方法实现角色的平滑转向。\r\n处理角色的移动,并将角色的移动方向和速度传递给 CharacterController 的 Move() 方法。\r\n如果角色有Animator组件,则更新 Speed 和 MotionSpeed 动画参数,以反映角色的移动状态。")]
private void Move()
{
// set target speed based on move speed, sprint speed and if sprint is pressed根据移动速度、冲刺速度以及是否按下冲刺键来设置目标速度
float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;
// a simplistic acceleration and deceleration designed to be easy to remove, replace, or iterate upon一种简化的加速和减速设计,旨在便于移除、更换或迭代
// note: Vector2's == operator uses approximation so is not floating point error prone, and is cheaper than magnitude注意 Vector == 运算符使用近似,因此不会容易受到浮点数误差的影响,而且比计算大小更便宜。
// if there is no input, set the target speed to 0如果没有输入,将目标速度设置为0
if (_input.move == Vector2.zero) targetSpeed = 0.0f;
// a reference to the players current horizontal velocity对玩家当前水平速度的引用
float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;
float speedOffset = 0.1f;
float inputMagnitude = _input.analogMovement ? _input.move.magnitude : 1f;
// accelerate or decelerate to target speed加速或减速至目标速度
if (currentHorizontalSpeed < targetSpeed - speedOffset ||
currentHorizontalSpeed > targetSpeed + speedOffset)
{
// creates curved result rather than a linear one giving a more organic speed change/ 创建的是曲线结果,而非线性结果,从而提供更自然的速度变化
// note T in Lerp is clamped, so we don't need to clamp our speed请注意,Lerp 中的 T 会被限制,所以我们不需要限制我们的速度。
_speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude,
Time.deltaTime * SpeedChangeRate);
// round speed to 3 decimal places将速度四舍五入到小数点后三位
_speed = Mathf.Round(_speed * 1000f) / 1000f;
}
else
{
_speed = targetSpeed;
}
_animationBlend = Mathf.Lerp(_animationBlend, targetSpeed, Time.deltaTime * SpeedChangeRate);
if (_animationBlend < 0.01f) _animationBlend = 0f;
// normalise input direction归一化输入方向
Vector3 inputDirection = new Vector3(_input.move.x, 0.0f, _input.move.y).normalized;
// note: Vector2's != operator uses approximation so is not floating point error prone, and is cheaper than magnitude注意,Vector != 运算符使用近似,因此不容易出现浮点误差,并且比计算大小更便宜。
// if there is a move input rotate player when the player is moving如果有移动输入,当玩家移动时旋转玩家
if (_input.move != Vector2.zero)
{
_targetRotation = Mathf.Atan2(inputDirection.x, inputDirection.z) * Mathf.Rad2Deg +
_mainCamera.transform.eulerAngles.y;
float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity,
RotationSmoothTime);
// rotate to face input direction relative to camera position绕摄像机位置旋转以面向输入方向
transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
}
Vector3 targetDirection = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;
// move the player移动玩家
_controller.Move(targetDirection.normalized * (_speed * Time.deltaTime) +
new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);
// update animator if using character如果使用角色,请更新动画器
if (_hasAnimator)
{
_animator.SetFloat(_animIDSpeed, _animationBlend);
_animator.SetFloat(_animIDMotionSpeed, inputMagnitude);
}
}
[Tooltip("跳跃和重力处理处理角色的跳跃和重力逻辑。\r\n如果角色在地面上,则重置 _fallTimeoutDelta,并根据玩家的跳跃输入来决定是否进行跳跃。\r\n如果角色没有在地面上,则根据 _fallTimeoutDelta 来决定是否进入自由落体状态,并更新相应的动画参数。\r\n最后,根据 _verticalVelocity 和 Gravity 来计算角色的垂直速度,以实现重力效果。")]
private void JumpAndGravity()
{
if (Grounded)
{
// reset the fall timeout timer重置跌倒超时计时器
_fallTimeoutDelta = FallTimeout;
// update animator if using character如果使用角色,请更新动画器
if (_hasAnimator)
{
_animator.SetBool(_animIDJump, false);
_animator.SetBool(_animIDFreeFall, false);
}
// stop our velocity dropping infinitely when grounded在接地时阻止我们的速度无限下降
if (_verticalVelocity < 0.0f)
{
_verticalVelocity = -2f;
}
// Jump
if (_input.jump && _jumpTimeoutDelta <= 0.0f)
{
// the square root of H * -2 * G = how much velocity needed to reach desired heightH 的平方根 * -2 * G = 达到期望高度所需的速度是多少
_verticalVelocity = Mathf.Sqrt(JumpHeight * -2f * Gravity);
// update animator if using character如果使用角色,请更新动画器
if (_hasAnimator)
{
_animator.SetBool(_animIDJump, true);
}
}
// jump timeout/ 跳过超时
if (_jumpTimeoutDelta >= 0.0f)
{
_jumpTimeoutDelta -= Time.deltaTime;
}
}
else
{
// reset the jump timeout timer重置跳转超时计时器
_jumpTimeoutDelta = JumpTimeout;
// fall timeout掉落超时
if (_fallTimeoutDelta >= 0.0f)
{
_fallTimeoutDelta -= Time.deltaTime;
}
else
{
// update animator if using character如果使用角色,请更新动画器
if (_hasAnimator)
{
_animator.SetBool(_animIDFreeFall, true);
}
}
// if we are not grounded, do not jump如果我们没有站稳,就不要跳。
_input.jump = false;
}
// apply gravity over time if under terminal (multiply by delta time twice to linearly speed up over time)如果处于终端状态,则随时间施加重力(将增量时间乘以两次以随时间线性加速)
if (_verticalVelocity < _terminalVelocity)
{
_verticalVelocity += Gravity * Time.deltaTime;
}
}
[Tooltip(" 角度限制用于限制角度值在指定范围内,帮助防止角度值超出360度。")]
private static float ClampAngle(float lfAngle, float lfMin, float lfMax)
{
if (lfAngle < -360f) lfAngle += 360f;
if (lfAngle > 360f) lfAngle -= 360f;
return Mathf.Clamp(lfAngle, lfMin, lfMax);
}
[Tooltip("Gizmos绘制当游戏对象在场景视图中被选中时,调用此方法绘制虚拟的球体,用于表示角色是否接触地面。\r\n根据角色是否在地面上,绘制绿色或红色的球体。")]
private void OnDrawGizmosSelected()
{
Color transparentGreen = new Color(0.0f, 1.0f, 0.0f, 0.35f);
Color transparentRed = new Color(1.0f, 0.0f, 0.0f, 0.35f);
if (Grounded) Gizmos.color = transparentGreen;
else Gizmos.color = transparentRed;
// when selected, draw a gizmo in the position of, and matching radius of, the grounded collider当选中时,在着地碰撞器的位置绘制一个小工具,并匹配其半径
Gizmos.DrawSphere(
new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z),
GroundedRadius);
}
[Toolyip("动画事件处理OnFootstep() 和 OnLand() 是用于处理动画事件的方法。\r\nOnFootstep() 方法会在角色播放脚步动画时触发,并随机播放一组脚步音效之一。\r\nOnLand() 方法会在角色播放落地动画时触发,并播放落地音效。")]
private void OnFootstep(AnimationEvent animationEvent)
{
if (animationEvent.animatorClipInfo.weight > 0.5f)
{
if (FootstepAudioClips.Length > 0)
{
var index = Random.Range(0, FootstepAudioClips.Length);
AudioSource.PlayClipAtPoint(FootstepAudioClips[index], transform.TransformPoint(_controller.center), FootstepAudioVolume);
}
}
}
private void OnLand(AnimationEvent animationEvent)
{
if (animationEvent.animatorClipInfo.weight > 0.5f)
{
AudioSource.PlayClipAtPoint(LandingAudioClip, transform.TransformPoint(_controller.center), FootstepAudioVolume);
}
}
}
}
第二 BasicRigidBodyPush
using UnityEngine;
//[Range(0.5f, 5f)]是一个属性(Attribute),用于在Unity编辑器中为该变量创建一个滑动条,范围从0.5到5,初始值为1.1。
//当控制器在执行移动时撞击碰撞体时,会调用 OnControllerColliderHit。
//这可用于在对象与角色碰撞时推动对象
public class BasicRigidBodyPush : MonoBehaviour
{
[Header("BasicRigidBodyPush ")]
[Tooltip("主要功能是让一个第三人称角色能够推动物体。当角色控制器(CharacterController)碰到一个带有刚体(Rigidbody)的物体,并且该物体所在的层级在pushLayers中指定,同时角色的移动方向不是从下方碰撞物体时,脚本会根据角色的移动方向和设定的推力强度对物体施加推力。通过这种方式,可以在Unity中实现角色推动物体的效果,增强游戏的互动性。")]
public GameObject Playerprefab;
[Header(" ThirdPersonController")]
[Tooltip("指定推动的物体所在的层级用于指定哪些层级的物体可以被角色推动。在Unity中,物体可以分配到不同的层级,通过这种方式可以只对特定层的物体施加推力。=notthing。")]
public LayerMask pushLayers;
[Tooltip("是否可以推动物体这是一个布尔变量,用于控制角色是否可以推动物体。如果设置为false,角色将不会对任何物体施加推力,即使它们位于指定的层级中。。")]
public bool canPush;
[Header("推力强度")]
[Tooltip(" //[Range(0.5f, 5f)]是一个属性(Attribute),用于在Unity编辑器中为该变量创建一个滑动条,范围从0.5到5,初始值为1.1。")]
[Range(0.5f, 5f)] public float strength = 1.1f;//用于控制推力的强度
[Tooltip("私有方法:是一个在角色控制器(CharacterController)与Collider发生碰撞时调用的方法。当角色控制器碰撞到一个Collider时,会触发这个方法。ControllerColliderHit对象包含了碰撞的详细信息,如碰撞的Collider,碰撞的方向等。在这个方法中,首先检查canPush是否为true,如果是,则调用PushRigidBodies方法来处理碰撞对象。")]
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (canPush) PushRigidBodies(hit);
}
[Tooltip("这个方法用于处理具体的碰撞物体是否应该被推动。首先,检查碰撞的Collider是否附着了一个Rigidbody组件,以及这个刚体是否是Kinematic的(Kinematic刚体不响应物理引擎计算的力)。如果碰撞的物体没有刚体组件或刚体是Kinematic的,则直接返回,不进行任何操作。接下来,检查碰撞物体所在的层级是否在pushLayers中指定。如果没有,则返回。此外,还检查碰撞的方向是否是从下方(y方向小于-0.3),如果是,则不进行推送操作。最后,计算推送的方向,仅考虑水平运动(忽略y方向),然后根据角色的移动方向和设定的推力强度对物体施加推力。\r\n\r\n总结")]
private void PushRigidBodies(ControllerColliderHit hit)
{
// https://docs.unity3d.com/ScriptReference/CharacterController.OnControllerColliderHit.html
// make sure we hit a non kinematic rigidbody确保我们碰到的是非运动学刚体
Rigidbody body = hit.collider.attachedRigidbody;
if (body == null || body.isKinematic) return;
// make sure we only push desired layer(s)确保我们只推动所需的层
var bodyLayerMask = 1 << body.gameObject.layer;
if ((bodyLayerMask & pushLayers.value) == 0) return;
// We dont want to push objects below us我们不想把物体推到我们下面
if (hit.moveDirection.y < -0.3f) return;
// Calculate push direction from move direction, horizontal motion only仅根据移动方向的水平运动计算推动方向
Vector3 pushDir = new Vector3(hit.moveDirection.x, 0.0f, hit.moveDirection.z);
// Apply the push and take strength into account/ 考虑推动力和承受力
body.AddForce(pushDir * strength, ForceMode.Impulse);
}
}
////声音效果:当角色推动刚体时,添加声音效果以增强游戏体验。
// 视觉效果:增加粒子效果或动画效果,当角色推动刚体时,展示视觉上的反馈。
// 角度限制:增加对推力方向的角度限制,以防止角色从某些方向施加过大的推力。
// 速度限制:根据角色或刚体的速度添加不同的推力效果,例如运行时的推力比行走时强。
// 施加力的衰减:随着推力的增加,施加力的效果可能会衰减,增加这种物理效果可以使得游戏更具真实感。
// 交互提示:当角色接近可以推动的刚体时,显示一个提示给玩家,告知该物体可以被推动。
// 推力范围指示:在角色附近显示一个范围指示器,表明角色可以施加推力的区域。
// 推力音量和视觉效果的调整:根据推力强度的不同调整声音效果的音量和视觉效果的强度,以给玩家更直观的反馈。
// 刚体反应增强:为刚体添加更多的物理反应,例如旋转、弹跳等,以增加互动的趣味性。
// 根据玩家输入调整推力:例如,通过不同的按键或控制器输入,调整推力的大小和方向。
第三StarterAssetsInputs
using UnityEngine;//引入了 Unity 引擎的核心库。
#if ENABLE_INPUT_SYSTEM//于条件编译,如果在 Unity 编辑器中启用了 Input System(新的输入系统),则编译其中的代码,否则不编译。这使得代码可以兼容旧的输入系统和新的输入系统。
using UnityEngine.InputSystem;
#endif
namespace StarterAssets
{
public class StarterAssetsInputs : MonoBehaviour
{
[Tooltip("要负责处理玩家的输入,并将其存储在公共变量中,以便其他脚本可以访问和使用这些输入值。该类支持基本的移动、视角控制、跳跃和冲刺功能,并且可以通过 cursorLocked 和 cursorInputForLook 变量来控制光标的行为。如果启用了 Unity 的新的输入系统,则通过 OnMove, OnLook, OnJump 和 OnSprint 方法来获取输入值。当应用失去焦点时,光标会被解锁,当应用获得焦点时,光标会被重新锁定,以确保玩家在玩游戏时的体验。")]
public GameObject P1;
[Header("Character Input Values字符输入值")]
[Tooltip("存储玩家的移动")]
public Vector2 move;
[Tooltip("视角输入值")]
public Vector2 look;
[Tooltip("存储玩家的跳跃布尔类型表示状态的开启或关闭。")]
public bool jump;
[Tooltip("冲刺状态")]
public bool sprint;
[Header("Movement Settings移动设置")]
[Tooltip("用于存储移动设置,是否为模拟移动。")]
public bool analogMovement;
[Header("Mouse Cursor Settings鼠标光标设置")]
[Tooltip("用于存储光标锁定状态和是否使用光标输入来控制视角。r\n")]
public bool cursorLocked = true;
[Tooltip("用于存储光标锁定状态和是否使用光标输入来控制视角。\r\n")]
public bool cursorInputForLook = true;
#if ENABLE_INPUT_SYSTEM
[Tooltip("当玩家移动时调用。InputValue 是新的输入系统的输入值对象,MoveInput 方法会被调用,传入移动方向。")]
public void OnMove(InputValue value)
{
MoveInput(value.Get<Vector2>());
}
[Tooltip("当玩家查看时调用。如果 cursorInputForLook 为 true,则调用 LookInput 方法,传入视角方向。")]
public void OnLook(InputValue value)
{
if(cursorInputForLook)
{
LookInput(value.Get<Vector2>());
}
}
[Tooltip("当玩家跳跃时调用,JumpInput 方法会被调用,传入跳跃状态。")]
public void OnJump(InputValue value)
{
JumpInput(value.isPressed);
}
[Tooltip("当玩家冲刺时调用,SprintInput 方法会被调用,传入冲刺状态。\r\n")]
public void OnSprint(InputValue value)
{
SprintInput(value.isPressed);
}
#endif
[Tooltip("将玩家的移动输入值赋值给 move 变量。")]
public void MoveInput(Vector2 newMoveDirection)
{
move = newMoveDirection;
}
[Tooltip("将玩家的视角输入值赋值给 look 变量。")]
public void LookInput(Vector2 newLookDirection)
{
look = newLookDirection;
}
[Tooltip("将玩家的跳跃状态赋值给 jump 变量。")]
public void JumpInput(bool newJumpState)
{
jump = newJumpState;
}
[Tooltip("将玩家的冲刺状态赋值给 sprint 变量。\r\n")]
public void SprintInput(bool newSprintState)
{
sprint = newSprintState;
}
[Tooltip("当应用获得或失去焦点时调用。当应用获得焦点时,调用 SetCursorState 方法来锁定或解锁光标。")]
private void OnApplicationFocus(bool hasFocus)
{
SetCursorState(cursorLocked);
}
[Tooltip("根据传入的 newState 参数来设置光标锁定状态。如果 newState 为 true,则光标会被锁定(CursorLockMode.Locked),否则光标会被解锁(CursorLockMode.None)。")]
private void SetCursorState(bool newState)
{
Cursor.lockState = newState ? CursorLockMode.Locked : CursorLockMode.None;
}
}
}
4449

被折叠的 条评论
为什么被折叠?



