角色(玩家)有Capsule Collider , Rigid body , Character Controller.这是角色(玩家)检查器设置的截图。
这是角色控制器的脚本。
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的刚体上,但不确定是什么。
只是一个观察。Coroutines应该返回新的WaitForFixedUpdate(),因为物理学应该在FixedUpdate()循环中运行。