- Home /
The question is answered, right answer was accepted
How to keep an object within the camera view?
Hello Unity Community!
I am currently working on a 3D space combat game (chicken invaders styled). I would like to know how to always keep an object within the camera view, regardless of resolution. Do I need to change the camera's field of view according to each resolution? I am using a perspective camera. Should I switch to an orthographic camera instead?
Thank you very much!
-Ashky
if its render distance you're talking about just click on your camera and adjust the clipping planes
Answer by robertbu · Sep 29, 2014 at 03:19 PM
This will keep the pivot point a game object visible:
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
void Update() {
Vector3 pos = Camera.main.WorldToViewportPoint (transform.position);
pos.x = Mathf.Clamp01(pos.x);
pos.y = Mathf.Clamp01(pos.y);
transform.position = Camera.main.ViewportToWorldPoint(pos);
}
}
You can clamp it tighter if needed. Example:
pos.x = Mathf.Clamp(pos.x, 0.1, 0.9);
Viewport coordinates start at (0,0) in the lower left of the screen and go to (1,1) in the upper right. This code forces an object to have a viewport coordinate in the (0,0) to (1,1) range, and therefore to be on the screen.
Thank you robertbu so very much, i have been pulling my hair out trying to keep my playerobject inside a 2d camera that rotates on the z axis, this work perfectly and you just opened my eyes to many more possibilities.
This is a short and simple solution that works perfectly. Thanks!
Thank you, this can definitely be used in many ways to keep an object in view.
Great solution! $$anonymous$$ine was longer, so I changed to yours on my current videogame. Thank you.
Answer by sysameca · Sep 29, 2014 at 11:05 AM
I assume you want the object to move independent of the screen aspect ratio:
using System;
using System.Collections.Generic;
using System.Collections;
using UnityEngine;
public class Controller : MonoBehaviour
{
public float speed = 0.0f;
// The clamp margins
public float
clampMarginMinX = 0.0f,
clampMarginMaxX = 0.0f,
clampMarginMinY = 0.0f,
clampMarginMaxY = 0.0f;
// The minimum and maximum values which the object can go
private float
m_clampMinX,
m_clampMaxX,
m_clampMinY,
m_clampMaxY;
private void Start()
{
// Get the minimum and maximum position values according to the screen size represented by the main camera.
m_clampMinX = Camera.main.ScreenToWorldPoint(new Vector2(0 + clampMarginMinX, 0)).x;
m_clampMaxX = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width - clampMarginMaxX, 0)).x;
m_clampMinY = Camera.main.ScreenToWorldPoint(new Vector2(0, 0 + clampMarginMinY)).y;
m_clampMaxY = Camera.main.ScreenToWorldPoint(new Vector2(0, Screen.height + clampMarginMaxY)).y;
}
private void Update()
{
Vector3 direction = Vector3.zero;
// Going left
if (Input.GetKey(KeyCode.A))
{
direction = Vector2.right * -1;
}
// Going right
else if (Input.GetKey(KeyCode.D))
{
direction = Vector2.right;
}
if (transform.position.x < m_clampMinX)
{
// If the object position tries to exceed the left screen bound clamp the min x position to 0.
// The maximum x position won't be clamped so the object can move to the right.
direction.x = Mathf.Clamp(direction.x, 0, Mathf.Infinity);
}
if (transform.position.x > m_clampMaxX)
{
// Same goes here
direction.x = Mathf.Clamp(direction.x, Mathf.NegativeInfinity, 0);
}
transform.position += direction * (Time.deltaTime * speed);
}
}
Basically the idea is to clamp the movement direction so the object can't exceed the screen limits.I didn't wrote the code for up and down movement but basically it's almost the same.The clamp margins can define the movement square
][1]
I have placed this code inside my script, however, I think it does not work properly. This is how my current script looks: http://pastebin.com/cWch67aq . Only m_clamp$$anonymous$$inY and m_clamp$$anonymous$$axY are calculated, both being 50. The rest of the variables are 0, and the object does not move.
Sorry for the late response but robert actually answered your question with simpler method.The script works fine however you are setting the public margin variables through the script which will directly unset them to 0 or whatever the value is in the inspector.When you inherit from $$anonymous$$onobehaviour the public variables need to be set through the inspector in order the change to take effect.
Hi guys, Sharing some modification to robertu idea if you are using crossplatform input into vector3 movement. I am using this on my project.
public float h; //input axix x
public float v; //input axis y
private void FixedUpdate()
{
h = CrossPlatformInput$$anonymous$$anager.GetAxis(axisX);
v = CrossPlatformInput$$anonymous$$anager.GetAxis(axisY);
Vector3 viewPos = cam.WorldToViewportPoint(transform.position);
if (viewPos.y < 0.02f)
{
v = 1;
}
else if (viewPos.y > 0.99f)
{
v= -1;
}
if (viewPos.x < 0.01f)
{
h = 1;
}
else if (viewPos.x > 0.98f)
{
h = -1;
}
m_$$anonymous$$ove = v * Vector3.forward + h * Vector3.right;
}
Follow this Question
Related Questions
How can I make the player walk forwards to where the camera is facing 0 Answers
3D / Top-Down - Make a script to let the player zoom the camera in and out 0 Answers
Brickshooter tutorial: bounding camera movement 1 Answer
Fixing the camera's left side in a 2D Game in all screen resolutions 0 Answers