I am using the c# code below to drag a game object within a specific rectangular area. This works fine but the problem I have is that my object moves too fast and to slow it down I have tried using a speed variable. It limits the speed in the x direction correctly but for some reason it completely stops the object from moving in the Y direction. This happens even when I am only attempting to slow down the X direction as a test. My aim is to slow down the speed in both direction within the area.
Please advise what I am doing wrong here and any improvements I can make.
using UnityEngine;
using System.Collections;
public class drag : MonoBehaviour {
public float maxXValue = 9f;
Vector3 dist;
float posX;
float posY;
float speedX = 0.3f;
float speedY = 0.3f;
void OnMouseDown(){
dist = Camera.main.WorldToScreenPoint(transform.position);
posX = Input.mousePosition.x - dist.x;
posY = Input.mousePosition.y - dist.y;
}
void OnMouseDrag(){
Vector3 curPos = new Vector3(Input.mousePosition.x - posX, Input.mousePosition.y - posY, dist.z);
Vector3 worldPos = Camera.main.ScreenToWorldPoint(curPos);
if (GameManager.instance.gameStart == false) {
worldPos.x = Mathf.Clamp (worldPos.x, -5f, 5f);
worldPos.y = Mathf.Clamp (worldPos.y, -13f, -13f);
} else {
worldPos.x = Mathf.Clamp (worldPos.x * speedX, -maxXValue, maxXValue);//Even when just limiting the X
worldPos.y = Mathf.Clamp (worldPos.y, -17.2f, -13f); //value the object no longer
} //moves in the Y direction
transform.position = worldPos;
}
}
Related
Unity2D
How to make game object to face opposite from the position of another game object?
I have a fish that is going always forward and randomly rotating to make semi random movement,
and i want that in range of player(shark) the fish change direction opposite to shark and start moving faster(trying to escape). I have speed increase already but i doknt know how to make the opposite direction.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FishMove : MonoBehaviour
{
Rigidbody2D rb;
int rotZ = 0;
[SerializeField]
Transform target;
float speed;
bool move=true;
bool rotace = true;
[SerializeField]
int smerRotace;
[SerializeField]
float casRotace;
float nula;
[SerializeField]
Transform shark;
float fearRange=4;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
if (rotace)
{
rotace = false;
smerRotace = Random.Range(-1, 2);
if (smerRotace == 0) nula = 0.2f;
Invoke("Rotace", Random.Range(3.0f*nula, 9.0f*nula));
nula = 1;
}
rotZ += 2 * smerRotace;
float distance = Vector2.Distance(transform.position, shark.position);
if (distance < fearRange)
{
speed = 0.1f;
}
else
{
transform.rotation = Quaternion.Euler(0, 0, rotZ);
}
transform.position = Vector2.MoveTowards(transform.position, target.position, speed);
speed = 0.05f;
}
void Rotace()
{
rotace = true;
}
}
Notice: at the part when I am saying to add/subtract 90 (you’ll know when you get there), try adding 90, if that doesn’t work, try subtracting 90 to get the right result.
To make it move fully the opposite direction, you should do a few things. First, I will tell you about Mathf.Atan2(float y, float x). Atan2 is arctangent. Arctangent takes a position, and finds the amount of rotations to rotate at that object, in radians. Then, you would want to multiply by Mathf.Rad2Deg, or radians to degrees. It converts radians to degrees, which unity uses. Then, you would add some degrees to face the opposite direction.
Here is a way to make an object look away from the the mouse:
using UnityEngine;
using System;
using System.Collections.Generic;
public class LookAtMouse : MonoBehaviour
{
public GameObject obj;
Vector3 offset;
Vector3 mousePosition;
float rotation;
void Update()
{
mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
offset = mousePosition - obj.transform.position;
rotation = Mathf.Atan2(offset.y, offset.x) * Mathf.Rad2Deg - 90f;
obj.transform.rotation = Quaternion.Euler(0f, 0f, rotation);
}
}
Basically, the script gets the mouse position, and stores it in mousePosition. Then, it gets the offset of the mouse relative to obj. The rotation is the product of the arctangent of the offset and the amount of degrees in a radian (unity uses degrees, not radians), minus 90. Arctangent is 90 degrees off of the target, so people usually add 90 to get it to look at the target. We are looking away from the target, so we subtract 90 to be 180 degrees away, or half way.
We would do the same thing for your script; here it is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FishMove : MonoBehaviour
{
Rigidbody2D rb;
int rotZ = 0;
[SerializeField] Transform target;
float speed;
bool move=true;
bool rotace = true;
[SerializeField] int smerRotace;
[SerializeField] float casRotace;
float nula;
[SerializeField] Transform shark;
float fearRange=4;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
Vector3 offset;
float rotation;
void FixedUpdate()
{
if (rotace)
{
rotace = false;
smerRotace = Random.Range(-1, 2);
if (smerRotace == 0) nula = 0.2f;
Invoke("Rotace", Random.Range(3.0f*nula, 9.0f*nula));
nula = 1;
}
rotZ += 2 * smerRotace;
float distance = Vector2.Distance(transform.position, shark.position);
if (distance < fearRange)
{
speed = 0.1f;
offset = transform.position - shark.transform.position;
rotation = Mathf.Atan2(offset.y, offset.x) * Mathf.Rad2Deg - 90f;
transform.rotation = Quaternion.Euler(0f, 0f, rotation);
}
else
{
transform.rotation = Quaternion.Euler(0, 0, rotZ);
}
transform.position = Vector2.MoveTowards(transform.position, target.position, speed);
speed = 0.05f;
}
void Rotace()
{
rotace = true;
}
}
Tell me in the comments if it works or if it doesn't work.
I have this script below and I want my player to always move towards the rotation angle, which doesn't happen. It only changes direction when I click.
My purpose is for the player to move at all times and towards the rotation which should be controlled by mouse position/mouse x axis (kind of like auto-run, but always change rotation based on mouse, not just move right or left).
I've tried about 10 different methods, nothing worked so far...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovementController : MonoBehaviour
{
public float speed = 4;
public float rot = 0f;
public float rotSpeed = 80;
public float gravity = 8;
private Camera cam;
Vector3 moveDir = Vector3.zero;
CharacterController controller;
Animator anim;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController> ();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
float horizontalSpeed = 8.0f;
//Get the mouse delta. This is not in the range -1...1
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float z = horizontalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(0, h, 0);
//Move Input
if(controller.isGrounded){
if(Input.GetMouseButtonUp(1))
{
anim.SetInteger ("condition", 1);
moveDir = new Vector3 (0,0,1) * speed;
// moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if(Input.GetMouseButtonDown(1))
{
anim.SetInteger("condition", 0);
moveDir = Vector3.zero;
}
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
}
Transform.LookAt
Just get a cursor position and that's it
Vector3 direction = target.position - player.transform.position;
Quaternion finalPlayerRotation = Quaternion.LookRotation(direction);
player.transform.rotation = finalPlayerRotation;
This also works in some cases:
Vector3 direction = target.position - player.transform.position;
player.transform.right /*You may need to change the Right to upper, -upper, -Right depend on the player rotation and the target position*/ = direction;
My camera has to focus on an GameObject that can be scaled over time. How can I compute the camera position so that it is always at the same distance from this GameObject? I've already tried to do something like
camera.position.y += object.scaleFactor / 2;
camera.position.z -= object.scaleFactor / 2;
But the bigger the object becomes, the lesser it works. I'm thinking about using a bounding box, do you think it would work ?
Thanks a lot !
use this:
// compute this when scale is 1.0f
Vector3 originalPosition = camera.position;
Vector3 originalDistance = camera.position - gameObject.position;
// then use:
camera.position = originalPosition + originalDistance * gameObject.scaleFactor;
if this does not work, please describe your situation in more detail and i will edit the answer
for example: if you want that the camera keeps the distance to the object, you will have to use BoundingSphere.radius:
// compute this when scale is 1.0f
Vector3 originalPosition = camera.position;
Vector3 temp = camera.position - gameObject.position;
Vector3 originalDirection = temp.normalized;
float originalDistance = temp.magnitude - boundingSphere.radius;
// use this when object is scaled:
camera.position = originalPosition + originalDirection * (boundingSphere.radius + originalDistance);
public class ObjectRelativeScale : MonoBehaviour
{
public float ObjectScale = 1.0f;
private Vector3 _initialScale;
void Start()
{
_initialScale = transform.localScale;
}
void Update()
{
var cameraMainTransform = Camera.main.transform;
var plane = new Plane(cameraMainTransform.forward, cameraMainTransform.position);
float dist = plane.GetDistanceToPoint(transform.position);
transform.localScale = _initialScale * dist * ObjectScale;
}
}
Basically the way around is better, scale the object depending on the camera position.
Cheers!
I made a simple racing game. The camera follows the car (player) and its position and rotation is based on car's Y rotation. I want to smooth the camera rotation, but when it crosses 0 degree point, it rotates 360 degrees.
Here's the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Camera : MonoBehaviour {
public Transform camera, player;
void Update() {
Vector3 cameraPosition = camera.transform.position;
float cameraRotation = camera.eulerAngles.y;
float playerRotation = player.eulerAngles.y;
Vector3 playerPosition = player.transform.position;
cameraPosition.x = (Mathf.Sin((playerRotation / 180) * Mathf.PI) * -6 + player.position.x);
cameraPosition.y = playerPosition.y + 2.5f;
cameraPosition.z = (Mathf.Cos((playerRotation / 180) * Mathf.PI) * -6 + player.position.z);
camera.transform.position = cameraPosition;
cameraRotation = cameraRotation + (playerRotation-cameraRotation)/2;
camera.localRotation = Quaternion.Euler(20f, cameraRotation, 0f);
}
}
I figured out that this rotation is caused by smoothing script:
cameraRotation = cameraRotation + (playerRotation-cameraRotation)/2;
How to prevent this unwanted rotation?
This is how I would do it:
public int smoothSpeed = 1f; // Change accordingly to increase/decrease smooth speed.
Then in update:
Vector3 directionToCar = player.position - camera.position;
Quaternion desiredRotation = Quaternion.LookRotation(directionToCar);
camera.rotation = Quaternion.Slerp(camera.rotation, desiredRotation, Time.deltaTime * smoothSpeed);
On a side node, if this camera script is attached to the camera, you don't have to make a field referencing the camera's transform. You can simply do transform.position instead of camera.transform.position.
A simpler solution to using the Slerp is to use Mathf.SmoothDamp, which has a variant called Mathf.SmoothDampAngle which handles the looping correctly. I've also had success doing the wraparound by hand but its not a very rewarding experience
using UnityEngine;
public class RotFollow : MonoBehaviour
{
[SerializeField] Transform carTransform;
[SerializeField] float smoothTime = .4f;
float currentYAngle;
float targetYAngle;
float angleVel;
void Update()
{
targetYAngle = carTransform.rotation.eulerAngles.y;
currentYAngle = Mathf.SmoothDampAngle(currentYAngle, targetYAngle, ref angleVel, smoothTime);
transform.rotation = Quaternion.Euler(
transform.rotation.eulerAngles.x,
currentYAngle,
transform.rotation.eulerAngles.z);
}
}
im trying to do the tutorial in unity on the official unity website page, and i have some doubts, because the tutorial is kinda old and the things doesnt work right how he do it, so i already set the player and the background, and now i must write the script to put the player on move and check the colisions between the x and z axis, so what i did was basicly using the Math.clamp method, but when i set the x axis for example, to a min -6 and max 6, it just moves between -1 and 1 same happens for the z axis, and i dont know why it happen :S
here is the code
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
private Rigidbody rb;
public float velocity;
public float xMin, xMax, zMin, zMax;
void Start () {
rb = GetComponent<Rigidbody> ();
velocity = 3.0f;
xMin = -6.0f;
xMax = 6.0f;
zMin = -4.0f;
zMax = 7.0f;
}
// Update is called once per frame
void FixedUpdate () {
float xAxis = Input.GetAxis ("Horizontal");
float zAxis = Input.GetAxis ("Vertical");
rb.velocity = new Vector3 (xAxis, 0.0f, zAxis) * velocity;
rb.position = new Vector3 (Mathf.Clamp (xAxis, xMin, xMax), 0.0f, Mathf.Clamp (zAxis, zMin, zMax));
}
}
Mathf.Clamp sets the bounds for you values. So it can't go more or less than these. if you want the values to go further than -6 and +6, Just increase xMin, xMax, zMin, zMax values from inspector. And Input.GetAxis has range between -1 to +1 so you wont get further than that. So try multiplying the xAxis and zAxis values by some large number. 10 for example.
void FixedUpdate ()
{
float xAxis = Input.GetAxis ("Horizontal") * 10;
float zAxis = Input.GetAxis ("Vertical") * 10;
rb.velocity = new Vector3 (xAxis, 0.0f, zAxis) * velocity;
rb.position = new Vector3 (Mathf.Clamp (xAxis, xMin, xMax), 0.0f, Mathf.Clamp (zAxis, zMin, zMax));
}