Summary: I'm trying out stuff in unity to better understand it.I created a 3d object with a rigidbody and froze the y axis. I placed to camera to look downwards towards the 3d object where the object can move left, right and up,down using the x and z axis.
Problem: The problem is the player is going out of the boundaries of the screen.
This is my code which I have based from my own understanding (in the unity manuals) and from other peoples code that had the same problem.
private Vector3 transformPos;
void LateUpdate ()
{
//Defined the boundaries of the screen by using ViewPortToWorldPoint. I tried ViewportToWorldPoint as well and it did not work
float left = Camera.main.WorldToViewportPoint(Vector3.zero).x;
float right = Camera.main.WorldToViewportPoint(Vector3.one).x;
float top = Camera.main.WorldToViewportPoint(Vector3.zero).y;
float bottom = Camera.main.WorldToViewportPoint(Vector3.one).y;
//Brought the player transform from World units to screen unit. Where x is x, z from the 3d object acts as y, and y is z.
transformPos = Camera.main.WorldToViewportPoint (transform.position);
//This debug was to check if z is y in the ViewportPoint and it was
Debug.Log(transformPos);
float x = transformPos.x;
//Calling it z because I dont wanna confuse myself when I convert it back
float z = transformPos.y;
//This is where I start the clamping using if statements
if(transformPos.x <= left)
{
x = Mathf.Clamp(transformPos.x, 0.1f,0.9f);
}
else if(transformPos.x >= right)
{
x = Mathf.Clamp(transformPos.x, 0.1f,0.9f);
}
if(transformPos.y <= top)
{
z = Mathf.Clamp(transformPos.y, 0.1f,0.9f);
}
else if( transformPos.y >= bottom)
{
z = Mathf.Clamp(transformPos.y, 0.1f,0.9f);
}
//And then finally I convert it back to world unit where the values is just placed in. x is x, y of the 3d object remains the same, and z
transform.position = Camera.main.ViewportToWorldPoint(new Vector3(x,transform.position.y,z));
}
The picture below is what I got from this code:
As you can see from my main camera down right, it is completely outside the bounds of my screen and I cannot move it. So there is obviously something wrong with my code, but yet I don't understand where I am wrong.
Edit #1
The cube in the picture is the one I am using as my player
Edit #2
The code below is the player movement script I've attached on my player along with the above script. I don't think it is conflicting with it but just in case. The movement also has a bit of a problem (I'm trying to move the player using the phone tilt function), but I'm trying to fix it as well
Rigidbody playerRigidbody;
public float speed = 10;
private Vector3 movement;
private Vector3 tilt ;
// Start is called before the first frame update
void Start()
{
playerRigidbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
tilt = Input.acceleration.normalized;
tilt = Quaternion.Euler(90f, 0, 0) * tilt;
//movement = new Vector3(Input.acceleration.normalized.x, 0.0f, 0.0f);
}
void FixedUpdate()
{
// horizontal movement code through device rotation
//var movement = new Vector3(Input.acceleration.normalized.x, 0.0f, Input.acceleration.normalized.z);
//playerRigidbody.velocity = movement * speed;
MoveCharacter(tilt);
}
private void MoveCharacter(Vector3 direction)
{
//playerRigidbody.velocity = movement * speed;
playerRigidbody.MovePosition(transform.position (direction * speed * Time.deltaTime));
}
CodePudding user response:
private Vector3 transformPos;
void LateUpdate()
{
//Defined the boundaries of the screen by using ViewPortToWorldPoint. I tried ViewportToWorldPoint as well and it did not work
float LeftBottom = 1;
float RightBottom = 0;
float LeftTop = 1;
float RightTop = 0;
Debug.Log($"Left: {LeftBottom} \n Right: {RightBottom} \n Top: {LeftTop} \n Bottom: {RightTop}");
//Brought the player transform from World units to screen unit. Where x is x, z from the 3d object acts as y, and y is z.
transformPos = Camera.main.WorldToViewportPoint(transform.position);
//This debug was to check if z is y in the ViewportPoint and it was
Debug.Log(transformPos);
float x = transformPos.x;
//Calling it z because I dont wanna confuse myself when I convert it back
float z = transformPos.y;
//This is where I start the clamping using if statements
if (transformPos.x <= LeftBottom)
{
x = Mathf.Clamp(transformPos.x, 0.1f, 0.9f);
Debug.Log(x);
}
else if (transformPos.x >= RightBottom)
{
x = Mathf.Clamp(transformPos.x, 0.1f, 0.9f);
}
if (transformPos.y <= LeftTop)
{
z = Mathf.Clamp(transformPos.y, 0.1f, 0.9f);
}
else if (transformPos.y >= RightTop)
{
z = Mathf.Clamp(transformPos.y, 0.1f, 0.9f);
}
//And then finally I convert it back to world unit where the values is just placed in. x is x, y of the 3d object remains the same, and z
transform.position = Camera.main.ViewportToWorldPoint(new Vector3(x, z, 1));
}
CodePudding user response:
The above code works. Thank you @Ubaldo Vitiello. The reason Im adding my own answer here as well is to explain why the player will move for a bit before coming to a complete stop and then stutter. Took me a while but I finally understood the reason. This is because "WorldToViewportPoint" is incompatible with "rigidbody.MovePosition". Now this is just from my understanding so I could be wrong, but MovePosition is where the player's rigidbody is moved to the position that you specify. The position only occurs in World space. "WorldToViewportPoint" transforms world space into viewport space.This is why my player moved for a bit before completing to a dead stop because my second script attached to the player is converting it to viewport space. Now the reason why my player will then stutter is because I was then transforming the viewport space back to world space. These two codes are simply incompatible with each other, that is all. How I resolved it was using rigidbody.velocity