Home > Software design >  Shake camera on current position Unity3D
Shake camera on current position Unity3D

Time:05-19

I made script where camera follows the player and camera shaker for effects. But the problem is that camera starts shaking on it's default (0, 0, 0) position. It jumps to that position starts shaking and returns to player. How can I make camera shake on it's current position. Here's my code:

public Transform target;
public float smoothTime = 0.3F;
private Vector3 velocity = Vector3.zero;

private const float _COROUTINE_FREQUENCY = 0.05f;
private Camera _mainCamera;
private Vector3 _initCamPos;
private bool _shaking;

void Start()
{
    _mainCamera = Camera.main;
}

void Update()
{
    // Define a target position above and behind the target transform
    Vector3 targetPosition = target.TransformPoint(new Vector3(0, 0, -10));
     
    // Smoothly move the camera towards that target position
    transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);
    if (Bullet.hit && !_shaking){
        StartCoroutine(_ShakingCamera());
    }
}

public void Shake(){
    StartCoroutine(_ShakingCamera());
}

public IEnumerator _ShakingCamera(float magnitude = 0.2f)
{
    _shaking = true;

    _initCamPos = _mainCamera.transform.position;
    float t = 0f, x, y;
    while (t < 0.3f)
    {
        x = Random.Range(-0.35f, 0.35f) * magnitude;
        y = Random.Range(-0.35f, 0.35f) * magnitude;

        _mainCamera.transform.position = new Vector3(x, y, _initCamPos.z);

        t  = _COROUTINE_FREQUENCY;
        yield return new WaitForSeconds(_COROUTINE_FREQUENCY);
    }

    _mainCamera.transform.position = _initCamPos;
    _shaking = false;
}

CodePudding user response:

Basic principle should be like "Camera Target Position Shake-Offset"

public Transform target;
public float smoothTime = 0.3F;
private Vector3 velocity = Vector3.zero;

private const float _COROUTINE_FREQUENCY = 0.05f;
private Camera _mainCamera;
private Vector3 _initCamPos;
private bool _shaking;
private Vector3 shakeOffset = Vector3.zero; // the offset variable

void Start()
{
    _mainCamera = Camera.main;
}

void Update()
{
    // Define a target position above and behind the target transform
    Vector3 targetPosition = target.TransformPoint(new Vector3(0, 0, -10));
 
    // Smoothly move the camera towards that target position
    transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);
    if (Bullet.hit && !_shaking){
        StartCoroutine(_ShakingCamera());
    }

    _mainCamera.position = targetPosition   shakeOffset; // set camera position here, shakeOffset is 0,0,0 when not shaking. 
}

public void Shake(){
    StartCoroutine(_ShakingCamera());
}

    public IEnumerator _ShakingCamera(float magnitude = 0.2f)
    {
    _shaking = true;
    
    _initCamPos = _mainCamera.transform.position;
    float t = 0f, x, y;
    while (t < 0.3f)
    {
        x = Random.Range(-0.35f, 0.35f) * magnitude;
        y = Random.Range(-0.35f, 0.35f) * magnitude;

        shakeOffset = new Vector3(x,y, _initCamPos.z); // define shakeOffset here
    
        // _mainCamera.transform.position = new Vector3(x, y, _initCamPos.z); not required here, see Update()
        
        t  = _COROUTINE_FREQUENCY;
        yield return new WaitForSeconds(_COROUTINE_FREQUENCY);
    }

    // reset offset:
    shakeOffset = Vector3.zero;

    // _mainCamera.transform.position = // not required here, see Update() 
_shaking = false;
}

Then, whenever you want to move the camera (WASD, Mouse, Joystick...) you will just modify the targetPosition which then allows you to go crazy with the shakeOffset because you can Lerp that back to 0,0,0 whenever you want. So you can move the camera independent of the shake.

Note: Setting the position like I did here will "break" the SmoothDamp effect. You need to decide if the shake should be dampened, too, or if you want to move the camera smoothly and add the shake instantly (so if feels more aggressively). Also I didn't test this code, but hopefully you got the point and understood the priciple.

CodePudding user response:

Simple Solve, The initial location must be added to the position during shake, So Put this part:

_mainCamera.transform.position = _initCamPos   new Vector3(x, y);

Instead of:

_mainCamera.transform.position = new Vector3(x, y, _initCamPos.z);
  • Related