【发布时间】:2021-06-06 19:55:50
【问题描述】:
在 Unity 中,我正在创建一个第三人称游戏,摄像机跟随玩家,同时还能自行旋转。现在,当我旋转相机并且有一堵墙时,相机似乎穿过了墙。
我尝试在相机中添加一个球体对撞机和一个刚体,但这并没有帮助。我还创建了一个空的游戏对象,其中一个球体对撞机作为父级,并使相机成为一个子级。我还尝试使用球体对撞机创建一个空子。
我附上了一段视频以及我的相机脚本代码。照片中的阴影实际上是我的相机正在穿过的墙壁。 Video of wall clipping. 有关如何解决此问题的任何建议?谢谢!
public class OrbitCamera : MonoBehaviour
{
[SerializeField] private Transform target;
public float rotSpeed = 1.5f;
private float vertRotY;
private float horiRotX;
private Vector3 offSet;
// Start is called before the first frame update
void Start()
{
vertRotY = transform.eulerAngles.y;
offSet = target.position - transform.position;
}
void FixedUpdate()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, Vector3.forward, out hit, 100f))
{
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Wall")
{
print("touching wall");
}
}
// Update is called once per frame
void LateUpdate()
{
float horiInput = Input.GetAxisRaw("Horizontal");
float vertInput = Input.GetAxisRaw("Vertical");
if (horiInput != 0)
{
vertRotY += horiInput * rotSpeed;
}
else
{
vertRotY += Input.GetAxis("Mouse X") * rotSpeed * 3;
}
if (vertInput == 0)
{
horiRotX += Input.GetAxis("Mouse Y") * rotSpeed * 3;
horiRotX = Mathf.Clamp(horiRotX, -45f, 20f);
}
Quaternion rotation = Quaternion.Euler(-horiRotX, vertRotY, 0);
transform.position = target.position - (rotation * offSet);
//transform.Rotate(rotation.eulerAngles);
transform.LookAt(target);
//transform.RotateAround(target.transform.position, Vector3.up, vertRotY);
//transform.RotateAround(target.transform.position, Vector3.left, rotSpeed * 3);
}
}
这是我的玩家移动脚本:
public class RelativeMovement : MonoBehaviour {
[SerializeField] private Transform target;
public float moveSpeed = 6.0f;
public float rotSpeed = 15.0f;
public float jumpSpeed = 15.0f;
public float gravity = -9.8f;
public float terminalVelocity = -20.0f;
public float minFall = -1.5f;
private float _vertSpeed;
private ControllerColliderHit _contact;
private CharacterController _charController;
private Animator _animator;
//Physics force
public float pushForce = 3.0f;
// Use this for initialization
void Start() {
_vertSpeed = minFall;
_charController = GetComponent<CharacterController>();
_animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update() {
// start with zero and add movement components progressively
Vector3 movement = Vector3.zero;
// x z movement transformed relative to target
float horInput = Input.GetAxis("Horizontal");
float vertInput = Input.GetAxis("Vertical");
if (horInput != 0 || vertInput != 0) {
movement.x = horInput * moveSpeed;
movement.z = vertInput * moveSpeed;
movement = Vector3.ClampMagnitude(movement, moveSpeed);
Quaternion tmp = target.rotation;
target.eulerAngles = new Vector3(0, target.eulerAngles.y, 0);
movement = target.TransformDirection(movement);
target.rotation = tmp;
// face movement direction
//transform.rotation = Quaternion.LookRotation(movement);
Quaternion direction = Quaternion.LookRotation(movement);
transform.rotation = Quaternion.Slerp(transform.rotation, direction, rotSpeed * Time.deltaTime);
_animator.SetBool("isRunning", true);
}
else
{
_animator.SetBool("isRunning", false);
}
//_animator.SetFloat("Speed", movement.sqrMagnitude);
// raycast down to address steep slopes and dropoff edge
bool hitGround = false;
RaycastHit hit;
if (_vertSpeed < 0 && Physics.Raycast(transform.position, Vector3.down, out hit)) {
float check = (_charController.height + _charController.radius) / 1.9f;
hitGround = hit.distance <= check; // to be sure check slightly beyond bottom of capsule
}
// y movement: possibly jump impulse up, always accel down
// could _charController.isGrounded instead, but then cannot workaround dropoff edge
if (hitGround) {
if (Input.GetButtonDown("Jump")) {
_vertSpeed = jumpSpeed;
} else {
_vertSpeed = minFall;
_animator.SetBool("isJumping", false);
}
} else {
_vertSpeed += gravity * 5 * Time.deltaTime;
if (_vertSpeed < terminalVelocity) {
_vertSpeed = terminalVelocity;
}
if (_contact != null ) { // not right at level start
_animator.SetBool("isJumping", true);
}
// workaround for standing on dropoff edge
if (_charController.isGrounded) {
if (Vector3.Dot(movement, _contact.normal) < 0) {
movement = _contact.normal * moveSpeed;
} else {
movement += _contact.normal * moveSpeed;
}
}
}
movement.y = _vertSpeed;
movement *= Time.deltaTime;
_charController.Move(movement);
}
// store collision to use in Update
void OnControllerColliderHit(ControllerColliderHit hit) {
_contact = hit;
//Physics method portion
Rigidbody body = hit.collider.attachedRigidbody;
if(body != null && !body.isKinematic){
body.velocity = hit.moveDirection * pushForce;
}
}
} `
【问题讨论】:
标签: unity3d