首页 > 解决方案 > 为什么当角色在中间爬楼梯时,如果停止移动角色,他正在慢慢地往回走?

问题描述

角色(玩家)有胶囊对撞机、刚体、角色控制器。角色(玩家)检查器设置的屏幕截图:

字符设置

这是脚本字符控制器:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharacterController : MonoBehaviour
{
    public float moveSpeed = 10.0f;
    public float jumpForce = 2.0f;

    void Start()
    {

    }

    // Update is called once per frame
    void Update ()
    {
        float translatioin = Input.GetAxis("Vertical") * moveSpeed;
        float straffe = Input.GetAxis("Horizontal") * moveSpeed;
        translatioin *= Time.deltaTime;
        straffe *= Time.deltaTime;

        transform.Translate(straffe, 0, translatioin);

        if (Input.GetKeyDown("escape"))
        {
            Cursor.lockState = CursorLockMode.None;
        }

        transform.Translate(0, jumpForce * Input.GetAxis("Jump") * Time.deltaTime, 0);
    }
}

然后是播放器的主摄像机子项:摄像机检查器的屏幕截图:

相机检查员

使对象能够被拖动的脚本 Drag Rigidbody :

using System;
using System.Collections;
using UnityEngine;

namespace UnityStandardAssets.Utility
{
    public class DragRigidbody : MonoBehaviour
    {
        public bool useMouseHoldDown = true;

        [SerializeField] private Camera mainCamera;

        const float k_Spring = 50.0f;
        const float k_Damper = 5.0f;
        const float k_Drag = 10.0f;
        const float k_AngularDrag = 5.0f;
        const float k_Distance = 0.2f;
        const bool k_AttachToCenterOfMass = false;

        private SpringJoint m_SpringJoint;
        private bool isDragging;

        private void Awake()
        {
            if (!mainCamera) mainCamera = GetComponent<Camera>();
            if (!mainCamera) mainCamera = Camera.main;
        }

        private void Update()
        {
            if (!Input.GetMouseButtonDown(0) || isDragging) return;

            // Make sure the user pressed the mouse down
            if (!Input.GetMouseButtonDown(0))
            {
                return;
            }

            // We need to actually hit an object
            RaycastHit hit = new RaycastHit();
            if (
                !Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition).origin,
                                 mainCamera.ScreenPointToRay(Input.mousePosition).direction, out hit, 100,
                                 Physics.DefaultRaycastLayers))
            {
                return;
            }
            // We need to hit a rigidbody that is not kinematic
            if (!hit.rigidbody || hit.rigidbody.isKinematic)
            {
                return;
            }

            if (!m_SpringJoint)
            {
                var go = new GameObject("Rigidbody dragger");
                Rigidbody body = go.AddComponent<Rigidbody>();
                m_SpringJoint = go.AddComponent<SpringJoint>();
                body.isKinematic = true;
            }

            m_SpringJoint.transform.position = hit.point;
            m_SpringJoint.anchor = Vector3.zero;

            m_SpringJoint.spring = k_Spring;
            m_SpringJoint.damper = k_Damper;
            m_SpringJoint.maxDistance = k_Distance;
            m_SpringJoint.connectedBody = hit.rigidbody;

            StartCoroutine("DragObject", hit.distance);
        }


        private IEnumerator DragObject(float distance)
        {
            isDragging = true;

            var oldDrag = m_SpringJoint.connectedBody.drag;
            var oldAngularDrag = m_SpringJoint.connectedBody.angularDrag;
            m_SpringJoint.connectedBody.drag = k_Drag;
            m_SpringJoint.connectedBody.angularDrag = k_AngularDrag;

            if (useMouseHoldDown == true)
            {
                while (Input.GetMouseButton(0))
                {
                    var ray = mainCamera.ScreenPointToRay(Input.mousePosition);
                    m_SpringJoint.transform.position = ray.GetPoint(distance);
                    yield return null;
                }
            }
            else
            {
                while (!Input.GetMouseButton(0))
                {
                    var ray = mainCamera.ScreenPointToRay(Input.mousePosition);
                    m_SpringJoint.transform.position = ray.GetPoint(distance);
                    yield return null;
                }
            }
            if (m_SpringJoint.connectedBody)
            {
                m_SpringJoint.connectedBody.drag = oldDrag;
                m_SpringJoint.connectedBody.angularDrag = oldAngularDrag;
                m_SpringJoint.connectedBody = null;
            }

            isDragging = false;
        }
    }
}

在屏幕截图中,一些脚本被禁用只是为了测试,但即便如此,如果不继续使用 W 键将他向上移动,玩家也会下楼梯。释放 W 键时,玩家并没有跌倒而是下楼。

拖动对象(例如 3d 立方体)时也会出现问题,如果我拖动立方体然后在其周围移动鼠标光标过快会将玩家推向某个方向,直到玩家慢慢停止。我想问题出在 FPSController 上的刚体上,但不确定是什么。

标签: c#unity3d

解决方案


只是一个观察:协程应该做 yield return new WaitForFixedUpdate(),因为物理应该在 FixedUpdate() 循环中运行。


推荐阅读