Minigore style camera script

Hey everyone,

This is my first thread on the forum and have a question. I’m creating a small top-down 3D assets in a 2D environment mobile game (iOS Android), very similar to Minigore, which is available on the AppStore. I would like to have a similar camera behaviour as Minigore, what is does is that once you reach the edge of the level, the camera stops moving and only the player continues to move in the appropriate direction. Once the player moves back into the middle of the plane, the camera automatically starts following it again.

What I could do is cast rays and check if I’m hitting walls and determine what to do, based on the distance that I get back. I would need more than just one ray, probably more like 4-8 rays, to make it more accurate. Since this game is for a mobile platform, I’m not sure if I should go ahead with this method… from what I have read so far, ray casting every frame can be very expensive in terms of performance. I’m not very experienced with Unity, so I’m not sure how feasible this solution would be.

Another way I can think of implementing this, would be by creating some cubes around the walls, tag them, check for collision with the viewport camera size (not really sure how I would get that but let’s just assume I could have another cube around the camera showing whatever the user sees on the screen) and then determine whether or not the camera should move. The problem is, how do I know if the player has moved to the far left hand side in the X axis (imagine 2D plane/viewport) and is still in the middle of the Y axis and stop moving the camera in the X axis but let it freely move in the Y axis? In other words, how do I stop it from moving in one axis and still let it continue to move in the other? How do I know which axis the player is allowed to still move in?

I hope this makes sense. I’m still new to Unity, so any guidance/help would be greatly appreciated. If anyone could provide some pseudo code or even their own implementation of something like this, that would be really great for me to learn from.

Thank you in advance!

You could have triggers in the sky, which would prevent the camera from moving (Invisible colliders). This way you don’t have to do any Raycasting. Knowing which axis the camera can move in is also solved this way. :wink: Good luck!

Thanks for the reply, but I don’t really understand. How would I stop the camera from moving and then allow it to move again, once I enter/exit a trigger? Are you thinking of creating multiple triggers with multiple scripts in different positions? I don’t seem to grasp what exactly you mean, sorry.

If my understanding is correct, you need the camera to stop moving let’s say to the left at a certain point, but moving on the up/down axis (when looking from above). A simple way to do this is to obstruct the camera’s way. Just place a big cube at the height of the camera and shape it so it blocks it’s way to the left. Then add a collider to the camera (I don’t know if it is possible, but there probably is a way to “simulate” a collider through scripting) and it will stop moving to follow your player. Very minimalistic and may not work as expected, but give it a try :slight_smile:

Okay, I think now I understand what you mean. I’m unsure how I would script that, I’m using the existing ‘Camera Relative Controls’ prefab for mobile games in Unity. I figured out that the code that I’m interested in is located inside the ‘FollowTransform.js’ file, the Update() function.

function Update () 
{
	thisTransform.position = targetTransform.position;
	
	if ( faceForward )
		thisTransform.forward = targetTransform.forward;
}

thisTransform.position = targetTransform.position is what it makes the camera follow the player. How would I modify this script to get the desired result? Any ideas?

I don’t mean to be impatient but has anyone else got any suggestions for me please? I could really do with some help! :slight_smile:

You can do this using a custom mesh and a single sphere cast.
The setup will be something like this:

  1. Create a mesh to define the bounds of your level
  2. Create a new layer for this mesh. In the physics settings inspector disable all tick boxes for this layer so it doesn’t interact with other colliders.
  3. Add the mesh to your scene. Add a mesh collider and put it in the layer you just created.
  4. Create a script for constraining object movement to a layer. This is the tricky part, the script will look a bit like this:
// This is untested and may not compile...
public class ConstrainToLayers : MonoBehaviour
{
	public float m_radius;
	public LayerMask m_layers;
	
	Vector3 m_previousPosition;
	
	void Start()
	{
		m_previousPosition = transform.position;
	}
	
	void Update()
	{
		Vector3 currentPosition = transform.position;
		if (currentPosition != m_previousPosition)
		{
			Vector3 diff = currentPosition - m_previousPosition;
			Ray ray = new Ray(m_previousPosition, diff.normalized);
			RaycastHit hit;
			if (Physics.SphereCast(ray, m_radius, out hit, diff.magnitude, m_layers))
			{
				float distanceToMove = hit.distance - Mathf.Epsilon; // Subtract a small amount to avoid tunneling
				Vector3 newPosition = ray.GetPoint(distanceToMove);
				transform.position = newPosition;
				m_previousPosition = newPosition;
			}
			else
			{
				m_previousPosition = currentPosition;
			}
		}
	}
}
  1. Add the script to you camera object. Setup the radius and layer mask (just use the layer you created earlier) and give it a try.

Thanks a lot, I will give it a try after the weekend (I won’t have access to my laptop for the next few days, so unfortunately I have to wait till I can test it and try to make it work for my project). I appreciate you input though, I will report back once I’ve tried this method! :slight_smile: