【问题标题】:3rd Person Camera Clipping Walls in UnityUnity 中的第三人称相机剪裁墙
【发布时间】: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


    【解决方案1】:

    尝试使用碰撞器创建一个新的空游戏对象,并使其成为具有相同位置的相机的子对象。

    【讨论】:

    • 嘿。效果不太好,还有推荐吗?我还尝试创建一个以球体对撞机为父对象的空游戏对象,并使相机成为子对象。两种方法都没有奏效。谢谢。
    • 你的墙对撞机是什么网状对撞机?
    • 是的,墙上有一个网格对撞机。墙壁只是缩放的立方体。
    • @Dani K 然后尝试用盒子碰撞器替换墙壁的碰撞器,因为带有刚体的网格碰撞器不支持连续碰撞检测。
    • 我改变了它,让所有的墙壁都有一个盒子碰撞器,但即使相机上有一个球体碰撞器,它也不起作用。还有什么其他方法吗?顺便说一句,感谢您提供的所有帮助。
    猜你喜欢
    • 2012-11-03
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    相关资源
    最近更新 更多