过去 2 天我一直在尝试让 headbob 脚本运行,但我一直卡在检查控制器速度上,它一直返回零。我有 2 个脚本,playermotor(移动角色)和 headbob 脚本(根据控制器速度计算并应用 headbob),这两个脚本都位于玩家对象上,当我在 headbob 脚本中使用controller.velocity 时,它始终返回 0,0 ,0,但是当我在playermotor脚本中使用它时它工作正常。脚本的顺序是否导致此问题?我已经按照教程 1:1 完成了,唯一的区别是我使相机和电机脚本略有不同。 以下是脚本:
玩家电机脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMotor : MonoBehaviour
{
private CharacterController controller;
private Vector3 playerVelocity;
private PlayerLook look;
private float speed = 5f;
public float crouchSpeed = 2.5f;
public float walkSpeed = 5f;
public float sprintSpeed = 8f;
public float jumpHeight = 0.6f;
private float crouchTimer = 1f;
public float gravity = -9.8f;
private float standingHeight = 2;
private float crouchingHeight = 1;
private float targetHeight = 2;
private bool isGrounded;
private bool crouching= false;
private bool sprinting = false;
private bool lerpCrouch=false;
Vector3 initialCameraPosition;
void Start()
{
controller = GetComponent<CharacterController>();
look = GetComponent<PlayerLook>();
initialCameraPosition = look.cam.transform.localPosition;
}
// Update is called once per frame
void Update()
{
isGrounded = controller.isGrounded;
if(lerpCrouch)
{
crouchTimer += Time.deltaTime;
float p = crouchTimer / 1;
p *= p;
if(controller.height<standingHeight && targetHeight == standingHeight)
{
var castOrigin = transform.position + new Vector3(0, controller.height / 2, 0);
if (Physics.Raycast(castOrigin, Vector3.up, out RaycastHit hit, 0.2f))
{
var distanceToCeiling = hit.point.y - castOrigin.y;
targetHeight = Mathf.Max (controller.height + distanceToCeiling -0.1f,crouchingHeight);
}
}
controller.height = Mathf.Lerp(controller.height, targetHeight, p);
if(p>1)
{
lerpCrouch = false;
crouchTimer = 0f;
}
}
}
public void ProcessMove(Vector2 input)
{
Vector3 moveDirection = Vector3.zero;
moveDirection.x = input.x;
moveDirection.z = input.y;
controller.Move(transform.TransformDirection(moveDirection)*speed*Time.deltaTime);
playerVelocity.y += gravity * Time.deltaTime;
if(isGrounded &&playerVelocity.y <0)
{
playerVelocity.y = -2f;
}
if (!Mathf.Approximately(targetHeight, controller.height))
{
var halfHeightDifference = new Vector3(0, (standingHeight - controller.height) / 2, 0);
var newCameraPosition = initialCameraPosition - halfHeightDifference;
look.cam.transform.localPosition = newCameraPosition;
}
controller.Move(playerVelocity*Time.deltaTime);
}
public void Jump()
{
if(isGrounded)
{
playerVelocity.y = Mathf.Sqrt(jumpHeight*-3.0f * gravity);
}
}
public void Crouch()
{
crouching = !crouching;
sprinting = false;
if (crouching)
{
targetHeight = crouchingHeight;
speed = crouchSpeed;
}
else
{
targetHeight = standingHeight;
speed = walkSpeed;
}
crouchTimer = 0;
lerpCrouch = true;
}
public void Sprint()
{
if(!crouching)
{
sprinting = !sprinting;
if (sprinting)
{
speed = sprintSpeed;
}
else
{
speed = walkSpeed;
}
}
}
}
Headbob 脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeadBobController : MonoBehaviour
{
[SerializeField] private bool _enable = true;
[SerializeField, Range(0, 0.1f)] private float _amplitude = 0.015f;
[SerializeField, Range(0, 30)] private float _frequency = 10.0f;
[SerializeField] private Transform _camera = null;
[SerializeField] private Transform _cameraHolder = null;
private float _toggleSpeed = 3.0f;
private Vector3 _startPos;
private CharacterController _controller;
private void Awake()
{
_controller = GetComponent<CharacterController>();
_startPos = _cameraHolder.localPosition;
}
private void Update()
{
if (!_enable)
return;
CheckMotion();
ResetPosition();
_camera.LookAt(FocusTarget());
}
private void CheckMotion()
{
float speed = new Vector3(_controller.velocity.x, 0, _controller.velocity.z).magnitude;
Debug.Log(_controller.velocity.magnitude);
if (speed < _toggleSpeed)
return;
if (!_controller.isGrounded)
return;
PlayMotion(FootStepMotion());
}
private void PlayMotion(Vector3 motion)
{
_camera.localPosition += motion;
}
private Vector3 FootStepMotion()
{
Vector3 pos = Vector3.zero;
pos.y += Mathf.Sin(Time.time * _frequency) * _amplitude;
pos.x += Mathf.Cos(Time.time * _frequency / 2) * _amplitude * 2;
return pos;
}
private void ResetPosition()
{
if (_camera.localPosition == _startPos)
return;
_camera.localPosition = Vector3.Lerp(_camera.localPosition, _startPos, 1 * Time.deltaTime);
}
private Vector3 FocusTarget()
{
Vector3 pos = new Vector3(transform.position.x, transform.position.y + _cameraHolder.localPosition.y, transform.position.z);
pos += _cameraHolder.forward * 15.0f;
return pos;
}
}
我尝试过多种方法,但这种摇头方法最接近我想要的。
我想通了,我从废品重新制作了外观脚本,直接在相机上,并合并了向量,使其成为单个移动调用,这解决了所有问题。