我一直在研究这个控制器,我在一个小行星上行走。我使用四元数。Slerp,当我在行星上的某个点时,控制器会慢慢漂移,绕着Y轴旋转。我的想法是,它根据我的起始位置保存一个值,所以当我移动到不同的点时,Slerp函数正试图将我旋转到那个位置?我试过将脚本的不同部分移动到它们自己的自定义方法来找出问题所在,但我在这一点上有点困惑。任何帮助都将不胜感激!
我认为问题将出现在底部的两个方法NewRotation或RunWalkStand中。
`
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] private LayerMask _groundMask;
[SerializeField] private Transform _groundCheck;
[SerializeField] private Transform cam;
public float jumpCooldown = 1f;
public float groundCheckRadius = 0.3f;
private float speed = 8;
private float runSpeed = 2;
private float turnSpeed = 800f;
private float jumpForce = 500f;
private Rigidbody rb;
private Vector3 direction;
private GravityBody _gravityBody;
private Animator playerAnimator;
private GameObject planetRecall;
void Start()
{
_gravityBody = transform.GetComponent<GravityBody>();
playerAnimator = GetComponent<Animator>();
planetRecall = GameObject.FindGameObjectWithTag("Planet Recall");
}
void Update()
{
bool isCloseToGround = Physics.CheckSphere(_groundCheck.position, groundCheckRadius, _groundMask);
NewRotation();
if (Input.GetKeyDown(KeyCode.Space) && isCloseToGround)
{
Jump();
}
}
void FixedUpdate()
{
RunWalkStand();
}
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject == planetRecall)
{
playerAnimator.SetBool("Grounded", true);
}
}
private void Jump()
{
rb.AddForce(-_gravityBody.GravityDirection * jumpForce, ForceMode.Impulse);
playerAnimator.SetTrigger("Fly_trig");
playerAnimator.SetBool("Grounded", false);
}
private void NewRotation()
{
rb = transform.GetComponent<Rigidbody>();
Vector3 mouseRotationY = new Vector3(0f, Input.GetAxisRaw("Mouse X"), 0f);
Quaternion rightDirection = Quaternion.Euler(0f, mouseRotationY.y * (turnSpeed * Time.deltaTime), 0f).normalized;
Quaternion newRotation = Quaternion.Slerp(rb.rotation, rb.rotation * rightDirection, Time.deltaTime * 1000f);
rb.MoveRotation(newRotation);
//Move Side to Side
Vector3 sideToSide = transform.right * Input.GetAxisRaw("Horizontal");
rb.MovePosition(rb.position + sideToSide * (speed * Time.deltaTime));
}
private void RunWalkStand()
{
direction = new Vector3(0f, 0f, Input.GetAxisRaw("Vertical")).normalized;
Vector3 forwardDirection = transform.forward * direction.z;
bool isRunning = direction.magnitude > 0.1f;
//Walking
if (isRunning && !Input.GetKey(KeyCode.LeftShift))
{
rb.MovePosition(rb.position + forwardDirection * (speed * Time.deltaTime));
playerAnimator.SetFloat("Speed_f", 0.5f);
}
//Running
else if(isRunning && Input.GetKey(KeyCode.LeftShift))
{
rb.MovePosition(rb.position + forwardDirection * (speed * runSpeed * Time.deltaTime));
playerAnimator.SetFloat("Speed_f", 1f);
}
//Standing
else if(isRunning == false)
{
playerAnimator.SetFloat("Speed_f", 0f);
}
}
}
`
2条答案
按热度按时间atmip9wb1#
这可能是因为一个slerp不是一条直线空气线,所以当你接近端点时它的速度较小。
jc3wubiy2#
我“大部分”解决了这个问题,这是一个意想不到的解决方案。通过在检查器中冻结播放器的旋转来解决漂移(仍然不知道是什么导致播放器旋转)。然而,这导致了额外的抖动。我发现了两个问题。
1.如果我选择了层次结构中的任何游戏对象,并玩游戏,游戏是紧张的,但如果我点击它关闭到什么,游戏运行更顺利(不是完全更好,但更顺利)。
1.我使用的是一个重力脚本,它将重力施加到玩家的刚体上,我相信有多个东西同时作用于RB上,这会导致抖动。我正在考虑尝试大大简化项目,但是将脚本中的不同方法放入不同的Update方法中会有所帮助,具体取决于组合(不幸的是,不像FixedUpdate中的物理运动和LateUpdate中的相机那么简单)。