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;
Related
I am creating a simple game where you are locked in the center of the screen and must shoot things as they move toward you. The problem I am currently facing is that I can not launch a bullet in the direction of my mouse cursor. Currently, my code looks like this
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour {
PlayerScript playerScript;
public float xVel;
public float yVel;
public float direction;
private void Awake()
{
playerScript = FindObjectOfType<PlayerScript>();
//playerScript.AngleDeg is the direction the player is facing (based on mouse cursor)
transform.rotation = Quaternion.Euler(0, 0, playerScript.AngleDeg);
direction = transform.rotation.z;
//from the unit circle (x = cos(theta), y = sin(theta)
xVel = Mathf.Cos(direction * Mathf.PI);
yVel = Mathf.Sin(direction * Mathf.PI);
}
void Update () {
transform.position += new Vector3(xVel,yVel,0);
}
}
currently, when I run the code, the bullet shoots at an angle which is at the direction that is correct when the player is orientated sideways, but when orientated vertically is a full 45 degrees off.
Attach this as a component to your instantiated bullet object and it should work.
Transform playerTransform;
float bulletSpeed;
Vector3 directionToShoot
void Start()
{
playerTransform = FindObjectOfType<PlayerScript>().gameObject.transform;
bulletSpeed = 3f;
//Direction for shooting
directionToShoot = playerTransform.forward - Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
void Update()
{
//shoot
transform.Translate(directionToShoot * bulletSpeed * Time.deltaTime);
}
I made the script bellow for the camera to follow the player, but I don't want it to follow him on his X axis. So it should follow the player smoothly only on his Z axis. Any suggestions?
Camera Script:
public Transform Ball;
public float SmoothSpeed = 0.125f;
public Vector3 offset;
bool MoveCamera = true;
void Start () {
}
public void FixedUpdate () {
if(MoveCamera == true){
Vector3 desiredPosition = Ball.position + offset;
Vector3 SmoothedPosition = Vector3.Lerp(transform.position, desiredPosition, SmoothSpeed);
transform.position = SmoothedPosition;
}
if (transform.position.z >= 2f)
{
MoveCamera = false;
}
}
What about only changing the z component?
public void FixedUpdate () {
if(MoveCamera == true){
Vector3 desiredPosition = new Vector3(0, Ball.position.y + offset.y, Ball.position.z + offset.z);
Vector3 SmoothedPosition = Vector3.Lerp(transform.position, desiredPosition, SmoothSpeed);
transform.position = SmoothedPosition;
}
if (transform.position.z >= 2f)
{
MoveCamera = false;
}
}
public gameObject toFollow;
Vector3 camDistance;
public void Start(){
camDistance = toFollow.transform.position-Camera.main.position;
}
public void Update(){
Vector3 following = new Vector3(Camera.main.x,Camera.main.z,toFollow.transform.position.z-Camera.main.position.z);
Camera.main.transform.position = following;
}
i just threw this together so it may require a few tweaks, but it should get you where you need to go. alternatively.... you can add a rigidbody to the camera, and in the inspector tick the boxes for constraints on the x and y axis. this will allow it to move only on the z (if you go this route remember to turn of the gravity for the cameras rigidbody as well)
Anybody in 2019 need a camera to be offset a specific position from their 3d character? Here is an easy solution! Attach this script to the camera you want to follow the player. Select the player as your target in the Unity editor.
This script sets the new position of the camera to
(EDIT: Where did the LaTeX go?)
$v = <targetPosition.x + xOffset, targetPosition.y + yOffset, targetPosition.z + zOffset>$
Benefits of this script:
Camera orientation does not change, even if character turns (because camera is not parented to the player).
Works regardless of player position
Limitations:
- Because camera orientation is fixed, you need to make sure that your character is not obscured by scenery.
- This style of camera control is best-suited for a 3rd person orthographic projection.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Transform target;
Vector3 targetPos;
void Update()
{
targetPos = target.position;
transform.position = new Vector3(targetPos.x + 10f, targetPos.y + 8.571067812f, targetPos.z - 10f);
// transform.LookAt(target.transform);
}
}
My use-case required an orthographic projection. Orthographic angles are usually at a 30 degree angle of declination, so my offset is back 10 units, over 10 units, and up half that hypotenuse (that is, up 10*sqrt2 * 1/2). I also bumped the y-position up by the character's height (1.5 units), which I thought would give a better center for the camera target. This gives a y-offset of about 8.571067812.
I'm working on a third-person run-around game and there's a specific kind of movement I've wanted to achieve but I'm having trouble even imagining how it would work, let alone actually coding it.
Essentially, when holding left or right, I want the player to orbit the camera. Such a camera effect can be seen here. That's exactly what I want to achieve.
Here's my movement and camera code so far. I image I'll need to use the camera's Y rotation to achieve this but my tests haven't worked out. Any input would be appreciated!
Movement:
public int speed = 10;
public int rotationSpeed = 10;
public CharacterController cc;
Vector2 input;
Vector3 moveDir;
Vector3 lookDir;
Vector3 forward;
Transform camTransform;
public Transform model;
void Start () {
cc = GetComponent<CharacterController>();
camTransform = Camera.main.transform;
}
void GetInput() {
input.x = Input.GetAxisRaw("Horizontal");
input.y = Input.GetAxisRaw("Vertical");
}
void CalculateForward()
{
}
void Move()
{
moveDir.x = input.x;
moveDir.z = input.y;
if(moveDir.magnitude > 1)
{
moveDir.Normalize();
}
Vector3 rotatedDir = Camera.main.transform.TransformDirection(moveDir);
rotatedDir = new Vector3(rotatedDir.x, 0, rotatedDir.z);
rotatedDir = rotatedDir.normalized * moveDir.magnitude;
cc.Move(rotatedDir * speed * Time.deltaTime);
}
void ApplyGravity()
{
}
void FaceDir()
{
if (moveDir != Vector3.zero)
{
transform.rotation = Quaternion.Slerp(
transform.rotation,
Quaternion.LookRotation(-moveDir),
Time.deltaTime * rotationSpeed
);
}
}
private void FixedUpdate()
{
GetInput();
//ApplyGravity();
Move();
FaceDir();
ApplyGravity();
}
}
Camera:
[SerializeField]
private float distanceAway;
[SerializeField]
private float distanceUp;
[SerializeField]
private float smooth;
[SerializeField]
private Transform follow;
private Vector3 targetPosition;
private void Start()
{
follow = GameObject.FindWithTag("Player").transform;
}
private void LateUpdate()
{
targetPosition = follow.position + follow.up * distanceUp - follow.forward * distanceAway;
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smooth);
transform.LookAt(follow);
}
Movement around a circle is always in a direction tangential to the circle, so with each update you want to:
Set the Y rotation of the player to be looking directly at the Y axis of the camera
rotate the player 90 degrees left or right (depending on the direction you want to go)
move the player forward a distance that will depend on the speed with which you would like them to move
Remember it's impossible to traverse a circle perfectly because there are infinitely many points on a circle but this approach will approximate it well enough.
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.
I am making a plat former game and I'm having a problem in the camera position of the game im imitating the camera movement of the 1st version of the super mario bros but every time I move my character the camera will go up until the character will disappear. How can I fix it?
public Transform playerPos;
public Transform rigthCamBoundary;
public Transform levelEnd;
Vector3 destination;
Vector3 velocity = Vector3.zero;
private void Start()
{
destination = Vector3.ClampMagnitude(levelEnd.position, 22.8f);
destination = new Vector3(destination.x, destination.y, 13.5f);
}
private void FixedUpdate()
{
if (Vector3.Distance(playerPos.position, rigthCamBoundary.position) < 13.7f)
transform.position = Vector3.SmoothDamp(transform.position, levelEnd.position, ref velocity, .14f, 8.5f);
}
To freeze the y-axis, get the y-axis value when the game runs. After using Vector3.SmoothDamp, change the y-axis to that variable you got before then apply it to your transform.
public Transform playerPos;
public Transform rigthCamBoundary;
public Transform levelEnd;
Vector3 destination;
Vector3 velocity = Vector3.zero;
float yPos;
private void Start()
{
destination = Vector3.ClampMagnitude(levelEnd.position, 22.8f);
destination = new Vector3(destination.x, destination.y, 13.5f);
//Get the default camera y pos
yPos = transform.position.y;
}
private void FixedUpdate()
{
if (Vector3.Distance(playerPos.position, rigthCamBoundary.position) < 13.7f)
{
Vector3 tempPos = Vector3.SmoothDamp(transform.position, levelEnd.position, ref velocity, .14f, 8.5f);
//Apply the default camera y pos
tempPos.y = yPos;
transform.position = tempPos;
}
}
Note that I don't know if this code is attached to the camera but this answer assumes it is. Otherwise the solution still remains the-same but you just have to change transform.position.y and transform.position to something else.