How to use a mathematic equation to stop object going off screen? - c#

[SOLVED]
I've been following the Learn To Code By Making Games course (Block Breaker Section) from Udemy and I have a flippin' annoying issue. My paddle doesn't clamp properly to the values I put in. I would have had no trouble with this but I decided that I want a small menu on the left side with a speed controller, sound controller and lives. This means I cant just say that I want the paddle to stop on the edge of the screen.
​Observed Behavior:
​The paddle does not constrain itself to the area I put in. As the screen size changes the paddle will either go off the screen or will be stopped somewhere like the middle of the screen.
​What I Want It To Do:
​I want the paddle to stop when it hits the edge of my menu on the left and to stop when it hits the screen on the right. I also want this to stay the same as my screen size changes. So basically I need a mathematic equation that can determine these points and it needs to be able to adjust based on the screen size.
Here is my code for the paddle:​
using UnityEngine;
using System.Collections;
public class Paddle : MonoBehaviour {
public Texture texture;
public void Update () {
Vector3 paddlePos = new Vector3 (0.5f, this.transform.position.y , 0f);
float mousePosInBlocks = Input.mousePosition.x;
paddlePos.x = Mathf.Clamp(mousePosInBlocks, //Left Vaule, //Right Value);
this.transform.position = paddlePos;
}
}

this happens because Input.mousePosition returns position of mouse on screen, not in world space. just convert mousePosition into world position, and then assign its value to mousePosInBlocks.
using UnityEngine;
using System.Collections;
public class Paddle : MonoBehaviour {
public Texture texture;
public void Update () {
Vector3 paddlePos = new Vector3 (0.5f, this.transform.position.y , 0f);
float mousePosInBlocks = Camera.main.ScreenToWorldPoint(Input.mousePosition).x;
paddlePos.x = Mathf.Clamp(mousePosInBlocks, leftValue, rightValue);
this.transform.position = paddlePos;
}
}
Edit: Sorry, not WorldToScreenPoint, ScreenToWorldPoint

Try just setting the paddlePos to the new vector you're creating (in world space):
public Texture texture; // if needed for something outside this code
private Vector3 paddlePos;
private float mousePosInBlocks;
private float xValue;
private float leftValue;
private float rightValue;
public void Update () {
mousePosInBlocks = Camera.main.ScreenToWorldPoint(Input.mousePosition).x;
//compute leftValue on this line
//compute rightValue on this line
xValue = Mathf.Clamp(mousePosInBlocks, leftValue, rightValue);
paddlePos = new Vector3 (xValue, transform.position.y , 0f);
transform.position = paddlePos;
}
EDIT Based on updated question title, the following should work:
public Texture texture; // if needed for something outside this code
private Vector3 playerPosOnScreen;
private float mousePosInBlocks;
public void Update () {
playerPosOnScreen = Camera.main.WorldToScreenPoint(transform.position);
if (playerPosOnScreen.x > Screen.Width) {
transform.position = Camera.main.ScreenToWorldPoint (new Vector3 (Screen.Width, transform.position.y, transform.position.z);
} else if (playerPosOnScreen.x < 0f) {
transform.position = Camera.main.ScreenToWorldPoint (new Vector3 (0f, transform.position.y, transform.position.z);
}
}

Try something like this: (pseudo code, untested, to give you an idea)
Please check the comment for each step.
public void Update () {
// left bound
Vector3 left = Camera.main.ViewPortToScreenPoint(new Vector3(0f, 0f, 0f));
// Menu width
left.x += fmyMenuWidth; // Width of menu
// Right bound
Vector3 right= Camera.main.ViewPortToScreenPoint(new Vector3(1f, 1f, 0f));
// Temporary position vector
Vector3 paddlePos = Vector3.zero;
// capture mouse x
float mouseX = Camera.main.ScreenToWorldPoint(Input.mousePosition).x;
// capture mouse y
float mouseY= Camera.main.ScreenToWorldPoint(Input.mousePosition).y;
// Combine and limit the position's X-value, should not go off screen menu's width---->screen's width
paddlePos.x = Mathf.Max(Mathf.Min(right.x, mouseX), left.x);
// Combine and limit the position's Y-value, should not go off screen 0---->screen's height
paddlePos.y = Mathf.Max(Mathf.Min(right.y, mouseY), left.y);
// Finally set the bounded position
this.transform.position = paddlePos;
}

Related

Restricting cursor to a radius around my Player

I am currently working on an multiplayer shooter game. Basicly atm you play as a cube and you have your hand(red square) following the cursor ingame.
I want to restrict the cursor movement to a perfect circle around my player sprite.
See attached picture for clarification.
https://imgur.com/TLliade
Following script is attached to the "Hand" (red square).
public class Handscript : MonoBehaviour
{
void Update()
{
Cursor.visible = false;
Vector3 a = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
a.Set(a.x, a.y, transform.position.z);
transform.position = Vector3.Lerp(transform.position, a, 1f);
}
}
Now I want to restrict cursor movement inside my radius that is a public transform attached to my Player prefab like this:
//Hand radius
public float radius;
public Transform centerRadius;
I am hard stuck and new to coding overall and I could use a push in the right direction.
Basicly the same question is asked here if I am being to unclear:
https://answers.unity.com/questions/1439356/limit-mouse-movement-around-player.html
EDIT: My goal in the end is to have similar hand movement as in the legendary "Madness Interactive" game, found here:
https://www.newgrounds.com/portal/view/118826
EDIT2: It might be impossible to lock the cursor inside the radius circle. Is it possible to just have the GameObject "Hand" locked inside this radius?
EDIT3: This is the code I use and it works like a charm:
using System;
using UnityEngine;
public class Handscript : Photon.MonoBehaviour
{
[SerializeField] private GameObject Player2; //Drag your player game object here for its position
[SerializeField] private float radius; //Set radius here
public new PhotonView photonView; //Never mind this if its not a photon project
private void Start()
{
Cursor.visible = false;
}
void Update()
{
if (photonView.isMine) //Never mind this if statement if it isnt a photon project
{
Vector3 cursorPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
Vector3 playerPos = Player2.transform.position;
Vector3 playerToCursor = cursorPos - playerPos;
Vector3 dir = playerToCursor.normalized;
Vector3 cursorVector = dir * radius;
if (playerToCursor.magnitude < cursorVector.magnitude) // detect if mouse is in inner radius
cursorVector = playerToCursor;
transform.position = playerPos + cursorVector;
}
}
#if UNITY_EDITOR
private void OnDrawGizmosSelected()
{
UnityEditor.Handles.DrawWireDisc(transform.parent.position, Vector3.back, radius); // draw radius
}
#endif
}
Get vector from the player to the cursor:
Vector3 playerToCursor = cursorPos - playerPos;
Normalize it to get the direction:
Vector3 dir = playerToCursor.normalized;
Multiply direction by your desired radius:
Vector3 cursorVector = dir * radius;
Add the cursor vector to the player position to get the final position:
Vector3 finalPos = playerPos + cursorVector;

How do i make it into a smooth camera? (unity C# programming)

This is what i got and why does this website want me to put more explaining when i clarified above well i want to achieve a smooth camera control where the player is in the middle of the camera if the mouse is in the middle but as it moves toward a direction i want the camera to move just a little bit to reveal terrain (here i have 2 problems:
1.The camera doesnt move if the mouse is at the point 0,0 of the screen and i want it to be the center of the camera
2. the camera drifts away in that direction, it doesnt stop like i want to make it):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour {
// Camera cam = Camera.main.orthographicSize;
//Vector2 camcenter = new Vector2(cam * 2, camheight);
public GameObject mage;
private Vector3 offset;
public float mincam = 30f;
public float maxcam = 120f;
public bool mouse_smooth_cam = false;
// Update is called once per frame
void LateUpdate ()
{
offset = Input.mousePosition / 100 + transform.position - mage.transform.position;
transform.position = mage.transform.position + offset;
}
void Update()
{
HandleZoom();
}
private void HandleZoom()
{
float scrollValue = Input.mouseScrollDelta.y;
float newCamSize = Camera.main.orthographicSize - scrollValue*4;
Camera.main.orthographicSize = Mathf.Clamp(newCamSize, mincam, maxcam);
}
}
Instead of Input.mousePosition / 100 use Camera.main.ScreenToWorldPoint(Input.mousePosition)
also always use Time.deltaTime in Update methods
var PAN_SPEED = 30f;
var mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
offset = mousePos + transform.position - mage.transform.position;
transform.position = mage.transform.position + offset * Time.deltaTime * PAN_SPEED;

Shooting a projectile but goes in wrong direction - 2D game

I am trying to make a simple game where I am shooting a projectile when the user touches the screen, I first spawn 8 projectiles (sprites) and when the user touches the screen I would like the top projectile to fly in the touch direction. I was able to do this; However, every time I shoot, the projectile goes in the wrong direction, here is an image which will illustrate the issue.
Obviously the image is still here but the object will continue flying until it goes out of the screen and then gets destroyed.
Here is the code snippet that handles this
GameplayController.cs
if (Input.GetMouseButtonDown(0))
{
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
position = Camera.main.ScreenToWorldPoint(position);
GameObject target;
target = new GameObject();
target.transform.position = position;
Arrow comp = currentArrows[0].GetComponent<Arrow>();
comp.setTarget(target.transform);
comp.GetComponent<Arrow>().arrowSpeed = 12;
comp.GetComponent<Arrow>().shoot = true;
currentArrows.RemoveAt(0);
Destroy(target);
}
I know I am getting the mouse input here and not the phone touch and that's fine for me, later I will convert it to the touch input.
Arrow.cs
public bool shoot = false;
public float arrowSpeed = 0.0f;
public Vector3 myDir;
public float speed = 30.0f;
private Transform target;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(shoot)
{
transform.position += transform.right * arrowSpeed * Time.deltaTime;
}
}
public void setTarget(Transform targetTransform)
{
this.target = targetTransform;
Vector3 vectorToTarget = target.position - transform.position;
float angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * speed);
}
private void OnBecameInvisible()
{
print("Disappeared");
Destroy(gameObject);
Gameplay.instance.isShooting = false;
}
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
I think that your problem is that you're getting the screen coordinates by click, not the world coordinates, which is actually two different things. In order to direct your projectile correctly you need to convert your screen coordinates to world like it's done here.
The next thing is how you move the projectile:
transform.position += transform.right * arrowSpeed * Time.deltaTime;
You're moving the projectile to the right and then rotating it somehow. Maybe you should try to move it with Vector3.Lerp, which will be easier and rotate it with Transform.LookAt.

How to spawn object on mouse position?

When I click right click I want to create new sphere. And I don't know why this don't work. It creates a sphere, but definitely not on mouse position!
Vector2 mousePos;
public Transform mousePointer;
float mouseX, mouseY;
Vector3 spawnPoint;
void Start () {
}
void Update () {
if(Input.GetMouseButtonDown(1)){
mousePos = Input.mousePosition;
mouseX = Input.mousePosition.x;
mouseY = Input.mousePosition.y;
spawnPoint = new Vector3(mouseX, mouseY, 0);
Instantiate(mousePointer, spawnPoint, Quaternion.identity);
}
}
Try spawning the object relative to the camera.
For example, use spawnPoint = cameraPosition + new Vector3(mouseX, mouseY, 0); or something similar. Check out the related post: Create a cube relative to camera mouse position.
The object is being spawned in global coordinates.

trying to keep a game object within the screen left and right bounds in unity3d

I have this code bellow for my gameobject :
private float screenx;
Vector3 playerPosScreen;
void Start () {
screenx=Camera.main.pixelWidth-renderer.bounds.size.x ;
}
void update(){
playerPosScreen = Camera.main.WorldToScreenPoint(transform.position);
if (playerPosScreen.x >= screenx) {
//playerPosScreen.x=screenx;
transform.position=new Vector3 (screenx, transform.position.y,transform.position.z);
}
//txt.text = playerPosScreen.x.ToString();
else if(playerPosScreen.x<=renderer.bounds.size.x){
transform.position=new Vector3 (renderer.bounds.size.x, transform.position.y,transform.position.z);
}
}
I'm developing a 2D game with an orthographic camera,my problem is the gameobject is keep on going out of screen , am i missing something here ?
After some research i found a solution wish worked excellent with me :
Vector3 playerPosScreen;
Vector3 wrld;
float half_szX;
float half_szY;
void Start () {
wrld = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, 0.0f, 0.0f));
half_szX = renderer.bounds.size.x / 2;
half_szY = renderer.bounds.size.y /2 ;
}
void Update () {
playerPosScreen = transform.position;
if (playerPosScreen.x >=(wrld.x-half_szX) ) {
playerPosScreen.x=wrld.x-half_szX;
transform.position=playerPosScreen;
}
if(playerPosScreen.x<=-(wrld.x-half_szX)){
playerPosScreen.x=-(wrld.x-half_szX);
transform.position=playerPosScreen;
}
}
Firstly your function is never called because there is typo in its name. It should be Update not update.
Secondly the problem with coordinates is that the code is mixing screen coordinates and world coordinates. Screen coordinates go from (0, 0) to (Screen.width, Screen.height). Coordinates can be changed from world coordinates to screen coordinates with WorldToScreenPoint and back with ScreenToWorldPoint, in which the Z value is the distance of the converted point from camera.
Here is a complete code example, which can be used after changing the player's position to make sure that it is inside the screen area:
Vector2 playerPosScreen = Camera.main.WorldToScreenPoint(transform.position);
if (playerPosScreen.x > Screen.width)
{
transform.position =
Camera.main.ScreenToWorldPoint(
new Vector3(Screen.width,
playerPosScreen.y,
transform.position.z - Camera.main.transform.position.z));
}
else if (playerPosScreen.x < 0.0f)
{
transform.position =
Camera.main.ScreenToWorldPoint(
new Vector3(0.0f,
playerPosScreen.y,
transform.position.z - Camera.main.transform.position.z));
}

Categories

Resources