Let object glide to mouse with constant speed Unity C# - c#

I have a bullet object, that needs to glide to the mouse when the mouse is pressed (but should stop when it is released). I have tried multiple approaches, but every time the bullet accelerates, and makes circles around the mouse in a ellipse form (I also have gravity). How can I get it to just move towards the mouse at a constant speed?
This is my code:
using UnityEngine;
public class Bullet : MonoBehaviour {
public Rigidbody rigidbody;
void Start() {
rigidbody = GetComponent<Rigidbody>();
rigidbody.useGravity = false;
rigidbody.velocity = new Vector3(0, -0.3F, 0);
}
float getX(Vector3 transform_pos, Vector3 mouse_pos) {
float tx = transform_pos.x;
float mx = mouse_pos.x;
if (tx == mx) { return 0;
} else if (tx > mx) { return -1;
} else if (tx < mx ) { return 1;
}else { return 0; }
}
void Update() {
if (Input.GetMouseButton(0)) {
Vector3 mouse_pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
transform.LookAt(mouse_pos);
float x = getX(transform.position, mouse_pos);
float y = transform.position.y > mouse_pos.y ? -0.03F : 0.03F;
rigidbody.AddForce(new Vector3(x, 0, transform.position.z), ForceMode.VelocityChange);
Debug.Log(x.ToString() + y.ToString());
}
if (transform.position.y < -5 | transform.position.y > 5) {
Destroy(transform.gameObject);
}
rigidbody.AddForce(Vector3.down, ForceMode.Force);
}
}

I tried a bit more, and found out, that using rigidbody.velocity() is better than rigidbody.AddForce(), so replace rigidbody.AddForce(new Vector3(x, 0, transform.position.z), ForceMode.VelocityChange); with rigidbody.velocity = new Vector3(x, y, transform.position.z); (replace x and y with the velocity and it should work. Note that this replaces the velocity, so all the movement will be stopped)

Related

Rotate Object Smoothly

i am trying to rotate object to 90 degrees smoothly on swipe here in my code its rotate instantly, how do i rotate object smoothly at given speed.
void Update()
{
if (fingerDown == false && Input.GetMouseButtonDown(0))
{
startPos = Input.mousePosition;
fingerDown = true;
}
if (fingerDown)
{
if (Input.mousePosition.x >= startPos.x + pixelDistToMove)
{
startPos = Input.mousePosition;
Vector3 rotationToAdd = new Vector3(0, 0, 90);
transform.Rotate(rotationToAdd);
fingerDown = false;
}
if (Input.mousePosition.x <= startPos.x - pixelDistToMove)
{
startPos = Input.mousePosition;
Vector3 rotationToAdd = new Vector3(0, 0, -90);
transform.Rotate(rotationToAdd);
fingerDown = false;
}
}
if (fingerDown && Input.GetMouseButtonUp(0))
{
fingerDown = false;
}
}
Thank you
transform.Rotate() rotates the object without animating it's rotation.
If you want it to rotate smoothly, you have to implement either an animation, or a turning state, or an IEnumerator.
My C# is a bit rusty, but I cooked this up:
public Vector3 desired_angle = Vector3.zero; // Turn the Gameobject to this angle
public float turn_time = 1f; // How long should turning take
public float rate = 60;
private void Update ()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(TurnTo());
}
}
IEnumerator TurnTo ()
{
Vector3 original_angle = transform.rotation.eulerAngles;
for (float i = 0f; i < 1f + turn_time / rate; i += turn_time / rate)
{
transform.rotation = Quaternion.Euler(Vector3.Lerp(original_angle, desired_angle, i));
yield return new WaitForSeconds(turn_time/rate);
}
}

How can I stop my camera clipping through terrain?

Having a bit of a problem in Unity3D. I have a fly camera with both a box collider and rigidbody, and it still moves through my terrain, which has a terrain collider and a rigidbody. The thing is, it interacts with my capsules just fine, bounces them away and everything. Obvious this is the exact opposite of what I want ha ha...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlyCamera : MonoBehaviour
{.
/*
Writen by Windexglow 11-13-10. Use it, edit it, steal it I don't care.
Converted to C# 27-02-13 - no credit wanted.
Simple flycam I made, since I couldn't find any others made public.
Made simple to use (drag and drop, done) for regular keyboard layout
wasd : basic movement
shift : Makes camera accelerate
space : Moves camera on X and Z axis only. So camera doesn't gain any height*/
float mainSpeed = 25.0f; //regular speed
float shiftAdd = 250.0f; //multiplied by how long shift is held. Basically running
float maxShift = 1000.0f; //Maximum speed when holdin gshift
float camSens = 0.25f; //How sensitive it with mouse
private Vector3 lastMouse = new Vector3(255, 255, 255); //kind of in the middle of the screen, rather than at the top (play)
private float totalRun = 1.0f;
void Update()
{
if (Input.GetKey(KeyCode.R))
{
transform.position = new Vector3(26f, 4f, 14f);
}
lastMouse = Input.mousePosition - lastMouse;
lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0);
lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x, transform.eulerAngles.y + lastMouse.y, 0);
transform.eulerAngles = lastMouse;
lastMouse = Input.mousePosition;
//Mouse camera angle done.
//Keyboard commands
float f = 0.0f;
Vector3 p = GetBaseInput();
if (Input.GetKey(KeyCode.LeftShift))
{
totalRun += Time.deltaTime;
p = p * totalRun * shiftAdd;
p.x = Mathf.Clamp(p.x, -maxShift, maxShift);
p.y = Mathf.Clamp(p.y, -maxShift, maxShift);
p.z = Mathf.Clamp(p.z, -maxShift, maxShift);
}
else
{
totalRun = Mathf.Clamp(totalRun * 0.5f, 1f, 1000f);
p = p * mainSpeed;
}
p = p * Time.deltaTime;
Vector3 newPosition = transform.position;
if (Input.GetKey(KeyCode.Space))
{ //If player wants to move on X and Z axis only
transform.Translate(p);
newPosition.x = transform.position.x;
newPosition.z = transform.position.z;
transform.position = newPosition;
}
else
{
transform.Translate(p);
}
}
private Vector3 GetBaseInput()
{ //returns the basic values, if it's 0 than it's not active.
Vector3 p_Velocity = new Vector3();
if (Input.GetKey(KeyCode.W))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(0, 0, 1);
}
}
}
}
if (Input.GetKey(KeyCode.S))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(0, 0, -1);
}
}
}
}
if (Input.GetKey(KeyCode.A))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(-1, 0, 0);
}
}
}
}
if (Input.GetKey(KeyCode.D))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(1, 0, 0);
}
}
}
}
return p_Velocity;
}
}
This flycam isn't mine so if it's not optimal for the use I'm looking for, please notify me about that too.
Basically you are. Transforming it not adding velocity thats why it is crossing the collider
You need to get reference of the rigidbody then add velocity to it
Then it won't cross the collider
You need to modify your code for that
Where you are transforming
Instead of transforming
You need to
Rigidbody.velocity= vector3(.....)
Never mind, I fixed the problem.
I ended up having Kinematic ticked on the box collider of the camera, so that must have messed it up.

Rotate 2D Sprite with Virtual Joystick

I am trying to rotate a GameObject along z-axis using Joystick, but its rotating y-axis. I might missed some math calculation. Any Help??
Reference Image
void FixedUpdate()
{
// get input from joystick
// get input from joystick
rightJoystickInput = rightJoystick.GetInputDirection();
float xMovementRightJoystick = rightJoystickInput.x; // The horizontal movement from joystick 02
float zMovementRightJoystick = rightJoystickInput.y; // The vertical movement from joystick 02
// if there is only input from the right joystick
if (rightJoystickInput != Vector3.zero)
{
// calculate the player's direction based on angle
float tempAngle = Mathf.Atan2(zMovementRightJoystick, xMovementRightJoystick);
xMovementRightJoystick *= Mathf.Abs(Mathf.Cos(tempAngle));
zMovementRightJoystick *= Mathf.Abs(Mathf.Sin(tempAngle));
// rotate the player to face the direction of input
Vector3 temp = transform.position;
temp.x += xMovementRightJoystick;
temp.z += zMovementRightJoystick;
Vector3 lookDirection = temp - transform.position;
if (lookDirection != Vector3.zero)
{
rotationTarget.localRotation = Quaternion.Slerp(rotationTarget.localRotation, Quaternion.LookRotation(lookDirection) * Quaternion.Euler(0, 45f, 0), rotationSpeed * Time.deltaTime);
}
}
}
You don't need most of the code in your question and this is really simple.
1.Find the angle with Mathf.Atan2 then multiple it with Mathf.Rad2Deg.
2.Use Quaternion.Euler(new Vector3(0, 0, angle)) to get the rotation then apply it to the Object.
This should be one in the Update function not FixedUpdate because FixedUpdate is used to move Rigidbody Objects.
public Transform rotationTarget;
public bool flipRot = true;
void Update()
{
rightJoystickInput = rightJoystick.GetInputDirection();
float horizontal = rightJoystickInput.x;
float vertical = rightJoystickInput.y;
float angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;
angle = flipRot ? -angle : angle;
rotationTarget.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
}
If using Rigidbody2D then use Rigidbody2D.MoveRotation in the FixedUpdate function. The rest of the code stays the-same.
public Rigidbody2D rg2d;
public bool flipRot = true;
void FixedUpdate()
{
rightJoystickInput = rightJoystick.GetInputDirection();
float horizontal = rightJoystickInput.x;
float vertical = rightJoystickInput.y;
float angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;
angle = flipRot ? -angle : angle;
rg2d.MoveRotation(angle);
}
EDIT:
But only the problem is when i leave joystick its rotation is setting
to 0 instantly which looks too odd. How can i fix it?
You have to detect when you release the joystick in OnPointerUp then slowly lerp the joystick thump back to the Zero position. You also have to lerp the current target object angle to zero or to its default value and this should be done in a coroutine function. When OnPointerDown is called, stop the current coroutine function. Prevent the code in FixedUpdate from running when finger is released so that it won't interfere with the coroutine function.
For the sake of completeness, below is the combination of a Joystick code and the Rigidbody answer above:
public class VirtualJoystickController : MonoBehaviour,
IDragHandler, IPointerUpHandler, IPointerDownHandler
{
private Image bgImg;
private Image joystickImg;
public float mas_distance = 7f;
void Start()
{
bgImg = GameObject.Find("JoystickBGImage").GetComponent<Image>(); // the joysticks background
joystickImg = GameObject.Find("Joystickthumb").GetComponent<Image>(); // the joystick object to use
}
private Vector3 _inputDirection = Vector3.zero;
//the movementDirection
public Vector3 joystickInputDirection
{
set
{
//Change only if value is different from old one
if (_inputDirection != value)
{
_inputDirection = value;
Debug.Log("Dir: " + _inputDirection);
}
}
get
{
return _inputDirection;
}
}
public void OnDrag(PointerEventData eventData)
{
dragJoyStick(eventData);
}
void dragJoyStick(PointerEventData eventData)
{
Vector3 tempDir = Vector3.zero;
Vector2 pos = Vector2.zero;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle
(bgImg.rectTransform,
eventData.position,
eventData.pressEventCamera,
out pos))
{
pos.x = (pos.x / bgImg.rectTransform.sizeDelta.x);
pos.y = (pos.y / bgImg.rectTransform.sizeDelta.y);
float x = (bgImg.rectTransform.pivot.x == 1) ? pos.x * 2 + 1 : pos.x * 2 - 1;
float y = (bgImg.rectTransform.pivot.y == 1) ? pos.y * 2 + 1 : pos.y * 2 - 1;
tempDir = new Vector3(x, y, 0);
if (tempDir.magnitude > 1)
{
tempDir = tempDir.normalized;
}
joystickImg.rectTransform.anchoredPosition = new Vector3(
tempDir.x * (bgImg.rectTransform.sizeDelta.x / mas_distance),
tempDir.y * (bgImg.rectTransform.sizeDelta.y / mas_distance));
joystickInputDirection = tempDir;
}
}
public void OnPointerDown(PointerEventData eventData)
{
released = false;
//Stop current coroutine
if (retCoroutine != null)
StopCoroutine(retCoroutine);
if (eventData.pointerCurrentRaycast.gameObject == bgImg.gameObject ||
eventData.pointerCurrentRaycast.gameObject == joystickImg.gameObject)
{
OnDrag(eventData);
}
}
public void OnPointerUp(PointerEventData eventData)
{
released = true;
//Stop current coroutine then start a new one
if (retCoroutine != null)
StopCoroutine(retCoroutine);
retCoroutine = StartCoroutine(SlowReturn(returnTime));
}
IEnumerator SlowReturn(float duration)
{
RectTransform thumbstickTransform = joystickImg.rectTransform;
Vector3 toPosition = Vector3.zero;
float counter = 0;
//Get the current position of the object to be moved
Vector2 currentThumb = thumbstickTransform.anchoredPosition;
while (counter < duration)
{
counter += Time.deltaTime;
//Slowly returns thumbstick
Vector2 tempThumbStickVal = Vector2.Lerp(currentThumb, toPosition, counter / duration);
joystickInputDirection = tempThumbStickVal;
thumbstickTransform.anchoredPosition = tempThumbStickVal;
//Slowly returns the target Object to original pos
float tempTargetObjAngle = Mathf.Lerp(angle, originalAngle, counter / duration);
rg2d.MoveRotation(tempTargetObjAngle);
yield return null;
}
}
public float returnTime = 1.0f;
public Rigidbody2D rg2d;
public bool flipRot = true;
const float originalAngle = 0;
bool released = true;
float angle;
Coroutine retCoroutine;
void FixedUpdate()
{
if (released)
return;
float horizontal = joystickInputDirection.x;
float vertical = joystickInputDirection.y;
angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;
angle = flipRot ? -angle : angle;
rg2d.MoveRotation(angle);
}
}
your function calculates a point where you want to look at:
Vector3 temp = transform.position;
temp.x += xMovementRightJoystick;
temp.z += zMovementRightJoystick;
Vector3 lookDirection = temp - transform.position;
this point is on the XZ plane, that is why the car rotates on Y axis
if you want to rotate on Z axis, calculate a point on XY plane like this:
Vector3 temp = transform.position;
temp.x += xMovementRightJoystick;
temp.y += zMovementRightJoystick;
Vector3 lookDirection = temp - transform.position;
PS: i don't know why you multiply with Quaternion.Euler(0, 45f, 0) - that is a constant angle on Y axis, it just means that each lookDirection will be rotated for 45 degrees - i would have to see your scene to know why you need this...

Seperate Camera and Player Movement in Unity

I'm currently trying to script a camera that has the player in focus and can move around unlinked to the players own movement.
You can control the camera with the right xBox controller.
The camera should move normally on the X axis in an orbit around the player, but if you move the camera to look up or down (let's say 20° up) it should be on 0° to focus the player again if u let off the joystick and interpolate between those two angles.
In my script the camera is able to look up and down (but the degree isn't locked yet so you could move it on the Y axis 360°+) but it resets to 0°. Additionally the x axis doesn't behave as I want it to since it is able to rotate around the player but only 180° and then it stops and if u let the controller go it also sets it's values back (which I don't want for the x axis).
The camera is a child object of an empty game object. The script is attached to the empty game object.
I'm trying to figure this out since ~3 days and I'd be really grateful for any small advice.
Thanks in advance & here's my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollowPlayer : MonoBehaviour
{
public GameObject target;
public GameObject cameraRig;
public float rotateSpeedX = 90.0f;
public float rotateSpeedY = 5f;
float cameraAngle;
float startCameraAngle;
Vector3 offset;
Vector3 currentOffset;
public float minRotationY;
public float maxRotationY;
bool isCameraMoving;
void Start()
{
offset = transform.position - target.transform.position;
cameraAngle = transform.localEulerAngles.z;
startCameraAngle = cameraAngle;
currentOffset = offset;
}
void Update()
{
transform.position = target.transform.position + currentOffset; // Folgt dem Spieler
float hor = Input.GetAxis("RightJoystickX") * rotateSpeedX; // Input rechter Joystick
float ver = Input.GetAxis("RightJoystickY") * rotateSpeedY;
if (!Mathf.Approximately (hor, 0)) {
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
}
if (!Mathf.Approximately (ver, 0)) {
cameraAngle += 110f * Time.deltaTime;
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
print(ver);
}
else if (ver <= 0.8f) {
//cameraAngle = Mathf.Lerp(cameraAngle, startCameraAngle, 1f - 0.1f * Time.deltaTime);
cameraAngle = startCameraAngle;
}
transform.localEulerAngles = new Vector3(0, hor, cameraAngle);
}
}
If sb else googled this and found my question this worked for me:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollowPlayer : MonoBehaviour
{
public GameObject target;
public GameObject cameraRig;
public float rotateSpeedX = 9.0f;
public float rotateSpeedY = 5f;
float cameraAngle;
float startCameraAngle;
Vector3 offset;
Vector3 currentOffset;
bool isCameraMoving;
void Start()
{
offset = transform.position - target.transform.position;
cameraAngle = transform.localEulerAngles.z;
startCameraAngle = cameraAngle;
currentOffset = offset;
}
void Update()
{
transform.position = target.transform.position + currentOffset; // Folgt dem Spieler
float hor = Input.GetAxisRaw("RightJoystickX") * rotateSpeedX; // Input rechter Joystick GetAxis wenn Bewegung ausschwingen soll
float ver = Input.GetAxisRaw("RightJoystickY") * rotateSpeedY; // GetAxis wenn Bewegung ausschwingen soll
if (!Mathf.Approximately (hor, 0)) {
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
}
if (ver != 0) {
//cameraAngle += 110f * Time.deltaTime;
if (ver > 0)
{
cameraAngle += 110f * Time.deltaTime;
if (cameraAngle >= 420f)
{
cameraAngle = 420f;
}
}
if (ver < 0)
{
cameraAngle -= 110f * Time.deltaTime;
if (cameraAngle <= 290f)
{
cameraAngle = 290f;
}
}
transform.RotateAround (target.transform.position, Vector3.up, hor);
currentOffset = transform.position - target.transform.position;
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, cameraAngle);
}
else
{
cameraAngle = Mathf.Lerp(startCameraAngle, cameraAngle, 1f - 0.9f * Time.deltaTime);
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, cameraAngle);
}

Rotating avatar at certain x coordinate Unity

I have a problem with turning my avatar at a certain position on the map. The character moves back and forth, but he doesn't want to rotate at coordinates i entered. What am i doing wrong?
this is my code:
sing System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AvatarPingPong : MonoBehaviour {
// Use this for initialization
public float speed;
public float startXCord, endXCord;
float endTrunx, startTurnx;
public GameObject obj;
Vector3 EndPoint, StartPoint;
void Start () {
EndPoint = transform.position;
endXCord = EndPoint.x;
endTrunx = EndPoint.x - 2f;
StartPoint = transform.position;
StartPoint.x = startXCord;
startTurnx = StartPoint.x + 2f;
}
// Update is called once per frame
void Update () {
transform.position = new Vector3(PingPong (Time.time * speed, startXCord, endXCord ), transform.position.y, transform.position.z);
if (transform.position.x == startTurnx ) {
Debug.Log("start Check");
obj.transform.Rotate(0f, 180f, 0f);
}
if (transform.position.x == endTrunx ) {
obj.transform.Rotate(0f, 180f, 0f);
Debug.Log("einde check");
}
}
//function to change the default starting value of (0, 0, 0) to any value
float PingPong(float t, float minLength, float maxLength) {
return Mathf.PingPong(t, maxLength-minLength) + minLength;
}
}
I believe the problem is that you're trying to flip your avatar once he reaches a particular x-coordinate, but he may never reach that EXACT coordinate. if (transform.position.x == startTurnx) will only return true if the two values are EXACTLY the same, and your avatar isn't actually moving smoothly across the screen. He's actually jumping minute amounts every frame, so he may never land on exactly that point.
Instead, my recommendation would be to compare his new position against his old position to see which direction he's traveling in and flip him when he changes direction. Some code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AvatarPingPong : MonoBehaviour {
// Use this for initialization
public float speed;
public float startXCord, endXCord;
float endTrunx, startTurnx;
public GameObject obj;
Vector3 EndPoint, StartPoint;
//I'm going to assume you start it moving left. You may have to change this
bool goingLeft = false;
void Start () {
EndPoint = transform.position;
endXCord = EndPoint.x;
endTrunx = EndPoint.x - 2f;
StartPoint = transform.position;
StartPoint.x = startXCord;
startTurnx = StartPoint.x + 2f;
}
// Update is called once per frame
void Update () {
float prevX = transform.position.x;
float newX = PingPong (Time.time * speed, startXCord, endXCord );
transform.position = new Vector3(newX, transform.position.y, transform.position.z);
if (newX > prevX) {
//avatar is moving to the right, check to see if that's the direction it was going last Update
if (goingLeft) {
Debug.Log("Flipping Right");
obj.transform.Rotate(0f, 180f, 0f);
goingLeft = false;
}
}else if (newX < prevX){
//avatar is moving to the left, check to see it that's the direction it was going last Update
if (!goingLeft) {
Debug.Log("Flipping Left");
obj.transform.Rotate(0f, 180f, 0f);
goingLeft = true;
}
}
}
//function to change the default starting value of (0, 0, 0) to any value
float PingPong(float t, float minLength, float maxLength) {
return Mathf.PingPong(t, maxLength-minLength) + minLength;
}
}

Categories