#Camera obstruction check

1 messages · Page 1 of 1 (latest)

ancient mirage
#

Here is my camera obstruction check code:

public class StayInView : MonoBehaviour
{
    [SerializeField] private GameObject PlayerObject;
    [SerializeField] private Transform OldPosition;
    
    [SerializeField] private LayerMask TerrainMask;
    private Cinemachine.CinemachineVirtualCamera Vcam;
    private Cinemachine.CinemachineTransposer transposer;

    private Vector3 NewPosition = new Vector3(0, 10, -6);

    private void Awake()
    {
        Vcam = GetComponent<CinemachineVirtualCamera>();
        transposer = Vcam.GetCinemachineComponent<CinemachineTransposer>();
        
    }

    private bool IsObstructed()
    {
        Vector3 DirToTarget = (PlayerObject.transform.position - transform.position).normalized;
        float DistToTarget = Vector3.Distance(transform.position, PlayerObject.transform.position);
        
        Debug.DrawLine(OldPosition.position, PlayerObject.transform.position);
        if (!Physics.Raycast(OldPosition.position, DirToTarget, DistToTarget, TerrainMask)) return true;
        
        return false;
    }

    private void FixedUpdate()
    {
        if (!IsObstructed())
        {
            Vcam.transform.rotation = Quaternion.Euler(90, 0, 0);
            
            transposer.m_FollowOffset = new Vector3(0, 10, -1.5f);
        }
        else
        {
            Vcam.transform.rotation = Quaternion.Euler(60, 0, 0);
            
            transposer.m_FollowOffset = new Vector3(0, 10, -6);
        }
    }
}
#

Normal Camera:

#

Camera If Obstruction Is found

#

If the object is less that 4 thick then the camera will switch between these two views every frame

#

OldPosition is the position the camera would be in if it wasn't in top down mode and this is where the raycast is sent from

#
public class FindOldCamPos : MonoBehaviour
{
    [SerializeField] private Transform PlayerPos;
    [SerializeField] private Vector3 NewPos;

    // Update is called once per frame
    private void Update()
    {
        Vector3 playerpos = PlayerPos.position;
        
        transform.position = playerpos + NewPos;
    }
}
ancient mirage
round wedge
ancient mirage
#

Oldposition is an empty gameobject that hovers above the player

#

its in the position of the normal camera view

#

and set through the inspector

round wedge
#

I see. Its a child of the player right?

ancient mirage
#

its not a child

#

it moves to its position every update because I didn't want it to rotate

#

the script I sent FindOldCamPos is attached to it

round wedge
#

Okay that makes sense. Sorry, missed that script+screenshot entirely when I was reading

ancient mirage
#

in this screen shot, the camera is alternating every frame even though the obstruction should be detected

#

as you can see the raycast is hitting the obstacle

#

object 1 has the problem but object 2 does not and it works as intended

#

I know it is caused by the thickness of the wall but I don't know why

round wedge
#

Can you check the collider on the faulty wall?

#

If it correctly represents the wall

ancient mirage
#

I know for sure that the collider is exact to the wall and it is on the right layer

round wedge
ancient mirage
#

Ok ill do that

#

it still doesn't work

#

is it possible that the line shown with DrawLine does not match the raycast being fired?

round wedge
#

Maybe. Try this :

private bool IsObstructed()
    {   
        Vector3 DirToTarget = (PlayerObject.transform.position - transform.position).normalized;
        float DistToTarget = Vector3.Distance(transform.position, PlayerObject.transform.position);
        Ray rayToCast = new Ray(transform.position, DirToTarget);
        Debug.DrawRay(ray.origin, ray.direction  * DistToTarget,  Color.red);
        if(! Physics.Raycast(ray, DistToTarget, TerrainMask)
          return true;
        return false;
    }
ancient mirage
#

I'm just trying your code now

#

why do you multiply direction by distance?

round wedge
#

Debug.DrawRay needs that. It draws the ray from the ray.origin point to ray.origin + the second parameter

ancient mirage
#

I fixed it!!!

#

I was using transform.position instead of OldPosition.position in my logic

round wedge
#

oh my god

ancient mirage
#

that is why the raycast was not matching the drawn line

round wedge
#

Why did I not see that

ancient mirage
#

still, its always helpful to explain your code to someone else as it helps you spot the error

#

In that way you were a huge help for me

round wedge
#

Glad that you figured it out! 🍀

ancient mirage
#

how would I move the camera smoothly between the two points?

round wedge
#

Lerping

ancient mirage
#

I tried lerp before but I don't fully understand it

round wedge
#

Cinemachine has other fancy techniques which do that (same thing internally). Although I'm not familiar enough with those

round wedge
ancient mirage
#

I could use two different virtual cameras instead of setting the position, that way cinemachine will handle the transition for me

#

the lerp made the camera move to a completely different place

round wedge
#

How were you using it?

ancient mirage
#

I dont remember because I deleted the lerp code

#

I dont know what to put in the float t part of lerp

#

I did 1 * time.deltatime and that screwed me up I think

#

also should the lerp be inside the update method or should it be a separate routine?

round wedge
#

Lerp is a basic math equation

#

t is the normalized % value between a & b which you want

#

So, when lerping, you increase t from 0 to 1 at a fixed rate

#

var lerpedValue = (lerpStart, lerpEnd, t)

#

So, lerpedValue goes from lerpStart to lerpEnd at a constant rate

round wedge
round wedge
round wedge
ancient mirage
#

does lerp need to be called once or does it move the vector by a small amout every time it is called?

round wedge
#

Lerp is a single frame operation

#

It will give you the same value each frame

#

Unless you change its parameters

ancient mirage
#

so calling lerp every frame is not good?

round wedge
#

Wait, I'll give you an example of how to use lerp

#
private float progress = 0f;
private Vector3 startPos;
private Vector3 endPos;
private float timeNeededForTravel = 2f;
private bool isLerping = true;
private void Start()
{
  startPos = transform.position;
  endPos = transform.position + new Vector3.one * 10;
}
private void Update()
{
  if(isLerping)
  {
      progress += Time.deltaTime;
      transform.position = Vector3.Lerp(startPos, endPos, progress / timeNeededForTravel);
  }
}```
#

This lerps the object from its inital position to [initial position + (10,10,10)] in 2 seconds

#

Does that make sense?

ancient mirage
#

I undertand it now

#

but when is progress reset?

round wedge
#

It is not reset in the above code. You can do so yourself however

#

when progress / timeNeededForTravel == 1

#

(Approximately equal since this is a float!)

ancient mirage
#

I like the lerp code but I'm just going to use two Vcams instead

#

the priority system lets me easily change to fixed cameras in certain areas too

#

Everything works properly now so I will close the thread