How To Rotate Objects Using C# Script In Unity2d? - c#

So I'm Trying To Rotate My Coin Object to 0z if Y is above 0.17f and if its not will rotate back to 90z , the first if statement works fine but the other one keeps rotating my coin and i don't know why...? I'm Completely New To Unity and C# Lang !
Anyway Here's my code :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoinScript : MonoBehaviour
{
public GameObject coin;
bool isRotated = false;
// Update is called once per frame
void FixedUpdate()
{
if (coin.transform.position.y > 0.17f && coin.transform.rotation.z >= 0f && !isRotated)
{
coin.transform.Rotate(coin.transform.rotation.x,coin.transform.rotation.y,-1f );
if (coin.transform.rotation.z <= 0f)
{
isRotated = true;
}
}else if (coin.transform.position.y < 0.17f && coin.transform.rotation.z <= 90f && isRotated)
{
coin.transform.Rotate(coin.transform.rotation.x,coin.transform.rotation.y,1f);
if (coin.transform.rotation.z >= 90f)
{
isRotated = false;
}
}
}
}

Transform.rotation is a Quaternion!
As the name suggests a Quaternion (also see Wikipedia -> Quaternion has not three but four components x, y, z and w. All these move within the range -1 to +1. Unless you really know exactly what you are doing you never touch these components directly.
If I understand you correctly you rather want to do something like e.g.
public class CoinScript : MonoBehaviour
{
public Transform coin;
public float anglePerSecond = 90;
private void FixedUpdate()
{
var targetRotation = coin.position.y > 0.17f ? Quaternion.identity : Quaternion.Euler(0, 0, 90);
coin.rotation = Quaternion.RotateTowards(coin.rotation, targetRotation, anglePerSecond * Time.deltaTime);
}
}

Related

Unity 2D NPC teleports instead of moving

I'm new to Unity and C#, but I'm trying to learn by making a basic RPG. I've gotten to a point, where my player character can move, but when I try to make an NPC walk to a specific point, it just teleports instantly.
using UnityEngine;
public class Walker : MonoBehaviour
{
public float walkerSpeed = 1.0f;
public void moveWalker(float x, float y)
{
Vector2 movement = new Vector2(x, y) * walkerSpeed;
movement *= Time.fixedDeltaTime;
transform.Translate(movement);
}
public void ScriptedWalk(float MoveToX, float MoveToY)
{
while (Mathf.Abs(MoveToX - transform.position.x) > 0.05f)
if (MoveToX > transform.position.x)
moveWalker(1, 0);
else
moveWalker(-1, 0);
}
}
I'm calling ScriptedWalk from my NPC's Start function, and I got stuck testing movement on the x axis. The NPC is in X = -2.5 and neds to get to X = 2.
What am I not understanding here?
Thank you Douglas, as you've suggested in your comment, I used a Coroutine, and changed my ScriptedWalk to this:
public IEnumerator ScriptedWalk(float MoveToX, float MoveToY)
{
if (Mathf.Abs(MoveToX - transform.position.x) < 0.05f)
{
// set animator floats to 0
stopWalker();
}
else
{
// Move east
if (MoveToX > transform.position.x)
moveWalker(1, 0);
// Move west
else
moveWalker(-1, 0);
}
yield return null;
}
I am also calling it from my FixedUpdate method.

How to get 8 direction Movement with controller sticks | Topdown 3D Unity

Im working on an 3d rpg top down view in Unity. Something like the zelda links awakening remake.
What im trying to achieve ist that the player rotates to the direction you press and then just goes forwards and this in only 8 directions.
I already got this working with WASD and the dpad, there it obviously works because you cant press in between two buttons if you know what i mean.
But i need a way to clamp the joystick input to only the 8 directions. How can i achieve this ? I hope you understand what i mean. This is the code ive already written. Note that im using the new input system.
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private PlayerInputActions playerInput;
private Rigidbody rb;
[SerializeField]
private float playerSpeed;
private float angle;
private Quaternion targetRotation;
private Vector2 input;
private Transform cam;
void Awake()
{
playerInput = new PlayerInputActions();
rb = GetComponent<Rigidbody>();
}
void Start()
{
cam = Camera.main.transform;
}
void Update()
{
GetInput();
if (input.x == 0 && input.y == 0) return;
CalculateDirection();
Rotate();
Move();
}
void GetInput()
{
input.x = playerInput.Player.Move.ReadValue<Vector2>().x;
input.y = playerInput.Player.Move.ReadValue<Vector2>().y;
}
void CalculateDirection()
{
if (input.sqrMagnitude > 1.0f)
input = input.normalized;
angle = Mathf.Atan2(input.x, input.y);
angle = Mathf.Rad2Deg * angle;
angle += cam.eulerAngles.y;
}
void Rotate()
{
targetRotation = Quaternion.Euler(0, angle, 0);
transform.rotation = targetRotation;
}
void Move()
{
//transform.position += transform.forward * 5 * Time.deltaTime;
rb.velocity = transform.forward * 200 * Time.fixedDeltaTime;
}
void OnEnable()
{
playerInput.Enable();
}
void OnDisable()
{
playerInput.Disable();
}
} ```
You can do something like this to keep results in the same way that you're working at moment
private void CalculateDirection (InputAction.CallbackContext context)
{
var input = context.ReadValue<Vector2>();
var x = Mathf.Abs(input.x) <= .1f ? 0f : // Deadzone
input.x > 0 ? 1f : -1f; // Direction
var y = Mathf.Abs(input.y) <= .1f ? 0f :
input.y > 0 ? 1f : -1f;
var angle = Mathf.Atan2(x, y);
angle = Mathf.Rad2Deg * angle;
}
As you are working with gamepad stick and values here can be a range between -1..1 and when you get interactions from your keyboard buttons values are coming in 0, 1, or -1, similar to the Input.GetAxisRaw() in older input system, we don't need to normalize it.
This approach should work but I have a feeling that this will give some weird behaviors when controlling with the stick, I mean, maybe if you try to go up the player ends going to some side (UpRight or UpLeft) because the range for upper, down, right and left aren't really wide, I hope to be wrong but if I'm right you'll probably need to bite the bullet and manually decide a range/angle for each of the 8 sides. Try the above code and if you need help manually creating it just come back here and we try again.
N

unity c# issue unable to get perfect position of a enemy in unity c# script using transform.position

when I command or set an enemy to go left and then at reaching a particular state or position i say my enemy to go right but it is not going right and not reaching to perfect position here is the code I think there is no issue in the code but it is not working properly so here are some images of the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enem : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.position = transform.position + new Vector3(-3f, 0f, 0f)* 1 * Time.deltaTime;
if (transform.position.x > -29)
{
transform.position = transform.position + new Vector3(3f, 0f, 0f) * 1 * Time.deltaTime;
}
}
}
Before adding any bool logic, try first simply moving your element:
using UnityEngine;
public class SimeMoveMove : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
transform.position += new Vector3(3f, 0f, 0f);
}
}
}
I smiled a little the moment I understood what you were trying to do.
I wrote the code imagining the result you were trying to make!
Create a cube, attach this code as component, and run the game.
// Gift for you friend
public class MoveTest : MonoBehaviour
{
private int _direction = 1;
void Start()
{
transform.position = Vector3.zero;
}
void Update()
{
Vector3 position = transform.position;
int direction = ShouldWeSwitchDirection(position.x, 0f);
if (direction != 0)
{
_direction = direction;
}
transform.position += _direction * new Vector3(3f, 0f, 0f) * 3f * Time.deltaTime;
}
private int ShouldWeSwitchDirection(float value, float center = 0f)
{
float direction = Mathf.Sign(value - center);
float distance = Mathf.Abs(value - center);
// If X Position is larger than 29
if (Mathf.Abs(distance) > 29)
{
// If X is on right side
if (direction >= 0)
{
return -1;
}
// If X is on left side.
else
{
return 1;
}
}
else
{
return 0;
}
}
}

How can I change a bullet shooting speed and keep the bullet shooting distance using physics?

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEditor;
using UnityEngine;
public class ShootBullets : MonoBehaviour
{
public float bulletDistance;
public bool automaticFire = false;
public float fireRate;
public Rigidbody bullet;
private float gunheat;
private bool shoot = false;
private GameObject bulletsParent;
private GameObject[] startpos;
// Start is called before the first frame update
void Start()
{
bulletsParent = GameObject.Find("Bullets");
startpos = GameObject.FindGameObjectsWithTag("Pod_Weapon");
}
void Fire()
{
for (int i = 0; i < startpos.Length; i++)
{
Rigidbody bulletClone = (Rigidbody)Instantiate(bullet, startpos[i].transform.position, startpos[i].transform.rotation, bulletsParent.transform);
bulletClone.velocity = transform.forward * bulletDistance;
// The bullet or any ammo/weapon should be on Y rotation = 0
Destroy(bulletClone.gameObject, 0.5f);
}
}
// Update is called once per frame
void Update()
{
if (automaticFire == false)
{
if (Input.GetMouseButtonDown(0))
{
Fire();
}
}
else
{
if (shoot == true)
{
Fire();
shoot = false;
}
}
if (gunheat > 0) gunheat -= Time.deltaTime;
if (gunheat <= 0)
{
shoot = true;
gunheat = fireRate;
}
}
}
I want to keep the distance like in this line :
bulletClone.velocity = transform.forward * bulletDistance;
but also to control the bullet speed. maybe it's a problem when using physics ?
my problem is that the bullets shot too fast.
the question is if it's possible to control the speed and keep the distance using physics ?
and does the function Fire should be called from Update or FixedUpdate ?
I meant something different with "over lifetime" but it doesn't matter. The speed is currently only set once so it is only dependent on the distance you shot the bullet from. Not the distance left to the target.
If you want to keep distance in the equation but decrease the result, have you thought about dividing the speed? IE add something like this
bulletClone.velocity = transform.forward * bulletDistance / 3;
you can also compare the speed to a maximum value and decide on which to pick IE
if(bulletDistance < 30)
{
bulletClone.velocity = transform.forward * bulletDistance;
}
else
{
bulletClone.velocity = transform.forward * 30
}
You can set the speed to anything you want.

Move doors in unity3d, at specific points through script C#

I have two doors in my game. Initially they are closed. After that they open and will stop at specific points (pic attached as a sample). So far I have written a script, which rotates the door continuously. I want to stop them, like at 45 angle, need kind suggestion.
using UnityEngine;
using System.Collections;
public class rotate : MonoBehaviour
{
public string rotate_along = "y";
public float speed = 10.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
if (rotate_along == "y") {
this.transform.Rotate (0, speed, 0);
} else if (rotate_along == "x") {
this.transform.Rotate (speed * Time.deltaTime, 0, 0);
} else if (rotate_along == "z") {
this.transform.Rotate (0, 0, speed * Time.deltaTime);
} else {
print ( "please! check your cordinate for rotating for "+gameObject.name );
}
}
}
I suggest you to use Lerp or Slerp for this:
void Update() {
transform.rotation = Quaternion.Lerp(from.rotation, to.rotation, Time.time * speed);
}
[Source]
This will move your doors naturally smoothly like in real world and will let you avoid coding horror in vector space. Unity community has pretty much a lot of examples how quaternions works. Here you can find brief explanation of what is difference:
http://answers.unity3d.com/questions/389713/detaliled-explanation-about-given-vector3slerp-exa.html
You are rotating the doors at a constant velocity without setting a maximum angle..
Something like this should do the trick.. But I haven't been able to test it.
using UnityEngine;
using System.Collections;
public class rotate : MonoBehaviour
{
public string rotate_along = "y";
public float speed = 10.0f;
private float _currentAngle = 0.0f;
private float _targetAngle = 45.0f;
private float _completed = false;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
if (_completed)
return;
float angle = speed * Time.deltaTime
if (_currentAngle + angle > _targetAngle)
{
angle = _targetAngle - _currentAngle;
_completed = true;
}
if (rotate_along == "y")
{
this.transform.Rotate (0, angle, 0);
}
else if (rotate_along == "x")
{
this.transform.Rotate (angle, 0, 0);
} else if (rotate_along == "z")
{
this.transform.Rotate (0, 0, angle);
}
else
{
print ( "please! check your cordinate for rotating for "+gameObject.name );
}
_currentAngle += angle;
}
}

Categories