#Camera obstruction check
1 messages · Page 1 of 1 (latest)
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;
}
}
What is OldPosition? I don't see you setting it anywhere
Oldposition is an empty gameobject that hovers above the player
its in the position of the normal camera view
and set through the inspector
I see. Its a child of the player right?
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
Okay that makes sense. Sorry, missed that script+screenshot entirely when I was reading
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
I know for sure that the collider is exact to the wall and it is on the right layer
Sanity check, can you move the logic in FixedUpdate() to LateUpdate()?
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?
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;
}
Debug.DrawRay needs that. It draws the ray from the ray.origin point to ray.origin + the second parameter
I fixed it!!!
I was using transform.position instead of OldPosition.position in my logic
oh my god
that is why the raycast was not matching the drawn line
Why did I not see that
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
Glad that you figured it out! 🍀
how would I move the camera smoothly between the two points?
Lerping
I tried lerp before but I don't fully understand it
Cinemachine has other fancy techniques which do that (same thing internally). Although I'm not familiar enough with those
Which part did you not understand?
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
How were you using it?
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?
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
It can be either. Making it in a separate coroutine will help you understand it much better, since update timers can get a bit hard to track
tbh, I'd just use this unless you want a fancy(ier)transition
Example :
float lerpedValue = (0,1,t);
If you increase t in a coroutine or Update from 0-1, by adding Time.deltaTime each frame to it, lerpedValue will go from 0-1 in an interval of 1 second
does lerp need to be called once or does it move the vector by a small amout every time it is called?
Lerp is a single frame operation
It will give you the same value each frame
Unless you change its parameters
so calling lerp every frame is not good?
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?