1

I'm using unity extendedflycam.cs. I added a sphere collider and a rigidbody to it. The intend is to avoid the camera to go trough the ground and buildings. This is achieved only when the camera is flying at normal speed, but when the camera accelerates using the shift key, as the script is intended, it goes trough the ground and buildings. This is accomplished by a speed multiplier in the script itself. How can this be avoided? How can a camera have collisions even when accelerating?

I have the Rigid Body with no gravity, and a Mass, Drag and Angular Drag of 1000. This is the ExtendedFlycam.cs:

using UnityEngine;

{
    public class ExtendedFlycam : MonoBehaviour
    {
        public float CameraSensitivity = 90;
        public float ClimbSpeed = 4;
        public float NormalMoveSpeed = 10;
        public float SlowMoveFactor = 0.25f;
        public float FastMoveFactor = 3;

        private float _rotationX;
        private float _rotationY;

        // ReSharper disable once UnusedMember.Local
        private void Start()
        {
            _rotationX = transform.eulerAngles.y;
        }

        // ReSharper disable once UnusedMember.Local
        private void Update()
        {
            if (Input.GetMouseButton(1))
            {
                _rotationX += Input.GetAxis("Mouse X") * CameraSensitivity * Time.deltaTime;
                _rotationY += Input.GetAxis("Mouse Y") * CameraSensitivity * Time.deltaTime;
                _rotationY = Mathf.Clamp(_rotationY, -90, 90);
            }

            Quaternion targetRotation = Quaternion.AngleAxis(_rotationX, Vector3.up);
            targetRotation *= Quaternion.AngleAxis(_rotationY, Vector3.left);
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 4f);

            float speedFactor = 1f;
            if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) speedFactor = FastMoveFactor;
            if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) speedFactor = SlowMoveFactor;

            transform.position += transform.forward * NormalMoveSpeed * speedFactor * Input.GetAxis("Vertical") *
                                  Time.deltaTime;
            transform.position += transform.right * NormalMoveSpeed * speedFactor * Input.GetAxis("Horizontal") *
                                  Time.deltaTime;
            float upAxis = 0;
            if (Input.GetKey(KeyCode.Q)) upAxis = -0.5f;
            if (Input.GetKey(KeyCode.E)) upAxis = 0.5f;
            transform.position += transform.up * NormalMoveSpeed * speedFactor * upAxis * Time.deltaTime;
        }
    }
}
Ivan
  • 151
  • 1
  • 1
  • 9

1 Answers1

1

Use Rigidbody.AddForce instead:

You are clearly using Transform.Translate to move your camera. If you want your camera to move with full collisions then you cannot use translation (as it is possible for the translation to move your camera completely through an object before the next collision detection).

If you want to have the full capacity of collisions then you have to use Rigidbody.AddForce.

https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html

You will have to pay special attention to gravity, the kinematic property, etc on your object. However you should be able to control the object in a similar way to how you do with translation. For example:

rb.AddForce(transform.forward * thrust);

rb.AddForce(transform.forward * -thrust);

rb.AddForce(transform.right* thrust);

rb.AddForce(transform.right* -thrust);

Transform forward to move forward. Negative thrust to move backwards. You can also apply the thrust in the right direction and negative right direction. I would still use translation for rotation just because that will probably be easier for you.

You may want to set high friction on the object so that it comes to a stop quickly like when using translation.

Extended example:

public float thrust = 5f;
public Rigidbody rb;

void Start()
{
    rb = GetComponent<Rigidbody>();
}

void FixedUpdate()
{
    // Movement code.
    if (Input.GetKey(KeyCode.UpArrow))
    {
       rb.AddForce(transform.forward * thrust);
    }
    if (Input.GetKey(KeyCode.DownArrow))
    {
       rb.AddForce(transform.forward * -thrust);
    }
    if (Input.GetKey(KeyCode.RightArrow))
    {
       rb.AddForce(transform.right* thrust);
    }
    if (Input.GetKey(KeyCode.LeftArrow))
    {
       rb.AddForce(transform.right* -thrust);
    }

    // Your rotation code
    if (Input.GetMouseButton(1))
    {
        _rotationX += Input.GetAxis("Mouse X") * CameraSensitivity * Time.deltaTime;
        _rotationY += Input.GetAxis("Mouse Y") * CameraSensitivity * Time.deltaTime;
        _rotationY = Mathf.Clamp(_rotationY, -90, 90);
    }

    Quaternion targetRotation = Quaternion.AngleAxis(_rotationX, Vector3.up);
    targetRotation *= Quaternion.AngleAxis(_rotationY, Vector3.left);
    transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 4f);

}
Tyler S. Loeper
  • 816
  • 11
  • 22
  • I added the script in the question...So If I understand you well, I should change the "transform.position" to "rb.AddForce(transform.forward * thrust);" ? – Ivan Oct 10 '18 at 15:34
  • @Ivan, See the extended example. Set kinematic off, and set friction to whatever value best fits the movement you want. – Tyler S. Loeper Oct 10 '18 at 16:25
  • It works wonderfully. With defaults. But if I change the fast move factor to for example 10 it goes through objects all over again – Ivan Oct 10 '18 at 19:45
  • @Ivan, one other thing you can try is to swap the box/capsule collider for a Mesh Collider and Select Continuous on its Rigidbody. It should be able to detect collision up to a much higher speed. – Tyler S. Loeper Oct 11 '18 at 15:22
  • That didn't work either... The problem always comes up the moment you accelerate to an X factor using the shift key. That feature is a most in my case, so the problem needs to be solved for the collider system, not for the speed. – Ivan Oct 11 '18 at 19:47
  • I think those are all the contemporary solutions for this problem. The collider system has problems and this is one of them. If neither of these worked I think all that's left are hacks or compromises. Like scaling down your objects relative size. Putting a limit on max speed (if ray cast detects an object closer than x), increasing the relative size of things that are being collided with, or use ray casts to detect collisions ahead of time, etc. – Tyler S. Loeper Oct 15 '18 at 13:20
  • You may want yo use ray casts to detect that a collision is about to occur and start slowing down the object. That might be a fair middle ground. – Tyler S. Loeper Oct 15 '18 at 13:24
  • 1
    That is not the intend, but if I ever get a solution I'll post it here. Thanks anyway! – Ivan Oct 15 '18 at 15:08