New to C# and Unity, trying to have a pointer that follows a player around in 2D space but it is bound within a circle of radius 4. My code below produces some odd behaviour, the cursor seems to move farther away from the player, and is not bound by the radius.
void Update()
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = Camera.main.transform.position.z + Camera.main.nearClipPlane;
Vector3 centerScr = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, Camera.main.nearClipPlane));
Vector3 direction = mousePos - centerScr;
direction = Vector3.ClampMagnitude(direction, 4f);
transform.position = mousePos + direction;
}
}
Related
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;
I am making top-down shooter on Unity and I need to implement shotgun, which will release 5 rounds at a time, each next will have rotation 10 degrees less than previous (from 20 to -20 in total). Instantiating the bullet on firepoint, the velocity is applied to it by bullet script, attached to bullet prefab. I apply the rotation in instantiating method too, but the bullet just rotates around itself, not to direction it flying.
Shooting code:
Vector2 mouseScreenPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = (mouseScreenPosition - (Vector2) transform.position).normalized;
transform.up = direction;
GameObject newBullet1 = Instantiate(bullet, firePoint.position, Quaternion.Euler(0f, 0f, 20f)) as GameObject;
newBullet1.GetComponent<Bullet>().direction = direction;
GameObject newBullet2 = Instantiate(bullet, firePoint.position, Quaternion.Euler(0f, 0f, 10f)) as GameObject;
newBullet2.GetComponent<Bullet>().direction = direction;
Bullet code:
public Vector3 direction;
public float bulletSpeed;
void Update () {
GetComponent<Rigidbody2D>().velocity = new Vector3 (direction.x, direction.y, transform.position.z) * bulletSpeed;
}
You need to apply the rotation to the direction vector for each bullet. Formula for the rotation of a vector is...
x1 = x0*cos(angle) - y0*sin(angle);
y1 = x0*sin(angle) + y0*cos(angle);
Vector2 direction10 = new Vector2(direction.x*Mathf.cos(10*Mathf.Deg2Rad) - direction.y*Mathf.sin(10*Mathf.Deg2Rad), direction.x*Mathf.sin(10*Mathf.Deg2Rad) + direction.y*Mathf.cos(10*Mathf.Deg2Rad));
Vector2 direction20 = new Vector2(direction.x*Mathf.cos(20*Mathf.Deg2Rad) - direction.y*Mathf.sin(20*Mathf.Deg2Rad), direction.x*Mathf.sin(20*Mathf.Deg2Rad) + direction.y*Mathf.cos(20*Mathf.Deg2Rad));
newBullet2.GetComponent<Bullet>().direction = direction10;
newBullet3.GetComponent<Bullet>().direction = direction20;
... //etc
Can probably do this cleaner with a loop.
I want to move an instance of a gameObject along the outline of another gameobject. Its a 2D Project in Unity.
My current Code:
Vector3 mousePosition = m_camera.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(new Vector2(mousePosition.x, mousePosition.y), new Vector2(player.transform.position.x, player.transform.position.y));
if (hit.collider != null && hit.collider.gameObject.tag == "Player") {
if (!pointerInstance) {
pointerInstance = Instantiate(ghostPointer, new Vector3(hit.point.x, hit.point.y, -1.1f), Quaternion.identity);
} else if(pointerInstance) {
pointerInstance.gameObject.transform.position = new Vector3(hit.point.x, hit.point.y, -1.1f);
pointerInstance.gameObject.transform.eulerAngles = new Vector3(0f, 0f, hit.normal.x);
}
}
Unfortunately, the gameObject doesn't rotate towards the mouse and the position on the left side of the playerObject is also sometimes off. I tried to use Instantiate() with Quaternion.LookRotation(hit.normal), but no luck either.
Here a rough sketch of what I want to achieve:
Any help is appreciated. Thanks!
it's better to use Mathematical way instead of physical way(Raycasting),because in raycasting you have to throw ray several time for checking hit point and rotate your object,it makes lag in your game.
Attach this script to your instantiated object:
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour
{
public Transform Player;
void Update()
{
//Rotating Around Circle(circular movement depend on mouse position)
Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(Player.position);
targetScreenPos.z = 0;//filtering target axis
Vector3 targetToMouseDir = Input.mousePosition - targetScreenPos;
Vector3 targetToMe = transform.position - Player.position;
targetToMe.z = 0;//filtering targetToMe axis
Vector3 newTargetToMe = Vector3.RotateTowards(targetToMe, targetToMouseDir, /* max radians to turn this frame */ 2, 0);
transform.position = Player.position + /*distance from target center to stay at*/newTargetToMe.normalized;
//Look At Mouse position
var objectPos = Camera.main.WorldToScreenPoint(transform.position);
var dir = Input.mousePosition - objectPos;
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg);
}
}
Useful explanations
Atan2:
atan2(y,x) gives you the angle between the x-axis and the vector (x,y), usually in radians and signed such that for positive y you get an angle between 0 and π, and for negative y the result is between −π and 0.
https://math.stackexchange.com/questions/67026/how-to-use-atan2
Returns the angle in radians whose Tan is y/x.
Return value is the angle between the x-axis and a 2D vector starting at zero and terminating at (x,y).
https://docs.unity3d.com/ScriptReference/Mathf.Atan2.html
Mathf.Rad2Deg:
Radians-to-degrees conversion constant (Read Only).
This is equal to 360 / (PI * 2).
When i press LMB i am rotating my player towards the mouse position, what i also want to do is simulate shooting. So when clicking LMB i want to create a line from the player position to the mouse position. My big issue is that my player is moving and i cant seem to figure out how to get the start position of the ray.
As of now the ray renders from vector3(0,0,0) to the mouse position, which is not what i want. I want it to render from the PLAYER position to the mouse position.
Here is my code:
void Update () {
transform.Translate (Vector3.down * Time.deltaTime * movementSpeed, Space.World);
if (Input.GetButtonDown("Fire1")) {
Vector3 mousePos = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, 10);
Vector3 lookPos = Camera.main.ScreenToWorldPoint (mousePos);
lookPos = lookPos - transform.position;
float angle = Mathf.Atan2 (lookPos.y, lookPos.x) * Mathf.Rad2Deg + 90;
transform.rotation = Quaternion.AngleAxis (angle, Vector3.forward);
if (Time.time > nextFire)
{
nextFire = Time.time + fireRate;
StartCoroutine (shotEffect());
laserLine.SetPosition (1,this.transform.position+lookPos);
}
}
}
If your code is attached to player and laserLine.SetPosition() sets beginning and ending for your line i think that:
laserLine.SetPosition (1,this.transform.position+lookPos);
should looks:
laserLine.SetPosition (this.transform.position,this.transform.position+lookPos);
I want to drag my 2d object in unity2d using code with:
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new
Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
Problem is that my camera is also moving along x axis so when I click on gameobject to drag it, it moves along x axis. I want to make this gameobejct static so it will be in its place and won't move? Any suggestions?
Instead of using absolute screen-centric position, you can try using the speed of the mouse pointer. Something like:
if(beingDragged) {
transform.position += new Vector3(Input.GetAxis("Mouse X"),
Input.GetAxis("Mouse Y"), 0);
}
Another option is to use a variable to track the camera's movement since the start of the drag. Then you can subtract this movement offset from your calculation, so that the dragging is done in "World Space" rather than "Screen Space"
Sorry, but I couldn't implement your suggestion. Here is the code for dragging the object, when OnMouseDown() it always gets the position of moving camera.
void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
offset = gameObject.transform.position + Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
void OnMouseDrag()
{
Vector3 curScreenPoint = new Vector3(screenPoint.x, Input.mousePosition.y, screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint (curScreenPoint);
transform.position = curPosition;
}
}