How to rotate a GameObject more than once - c#

trying to use suggested option have an error vector3 right is not in its definition
line transform.Rotate(Vector3.Right
thank you in advance
using UnityEngine;
using System.Collections;
public class ForwardBack : MonoBehaviour {
// speed variable
public float speed;
public KeyCode pressLeft;
public KeyCode pressRight;
public float rotationSpeed;
// Use this for initialization
void Start () {
speed = 1f;
}
// Update is called once per frame
void Update () {
transform.Translate(0f, speed*Input.GetAxis("Vertical") * Time.deltaTime,0f);
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(Vector3.Right * rotationSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(Vector3.Left * rotationSpeed * Time.deltaTime);
}
}
}

Try Input.GetKey instead of Input.GetKeyDown
Input.GetKeyDown detects if a button is pressed, whereas Input.GetKey checks for a continuous press. I imagine that is why your cylinder is only turning once.

There are quite a few inefficiencies in your code. You should not call GetComponent<>() in the Update loop. Instead store a referece to it using the Start function and use that in the Update loop:
public class ForwardBack : MonoBehaviour
{
private Transform thisTransform = null;
void Start ()
{
// Get refrence
thisTransform = GetComponent<Transform>();
}
void Update ()
{
//Use refrence.
thisTransform.Rotate(Vector3.right * Time.deltaTime);
}
}
Note: You might realise that every child of MonoBehaviour inherits the transform property which will look up a reference to the Transform component. Using this is inefficient. You should get your own reference like I have shown here.
Edit:As noted by #JoeBlow the transform property may be fine to use. There is nothing mentioned about how it returns the Transform component in the Unity docs. I have read that it is just a wrapper for GetComponent though from a few different sources. Use at your own discretion.
Secondly, don't use eulerAngles to rotate. It even says so in the docs.
Only use this variable to read and set the angles to absolute values. Don't increment them, as it will fail when the angle exceeds 360 degrees. Use Transform.Rotate instead.
It looks like you're not even incrementing the angle, just setting it to new Vector3(0, 0, -90) anyways which means even if you did do this it will just be set to that value rather than slowly increasing.
The docs for eulerAngles also lead you to what you should be using which is Transform.Rotate.To get this to work you will have to change the input method to Input.GetKeyrather than Input.GetKeyDown but this has already been mentioned in one of the other answers. Then you can rotate around your desired axis. Remember to use Time.deltaTime to scale the value so as it rotates at the same speed no matter what framerate you have. Your code for rotation might look something like this:
public class ForwardBack : MonoBehaviour
{
public float roatationSpeed;
private Transform thisTransform = null;
void Start ()
{
thisTransform = GetComponent<Transform>();
}
void Update ()
{
if(Input.GetKey(KeyCode.RightArrow)
{
thisTransform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);
}
if(Input.GetKey(KeyCode.LeftArrow)
{
thisTransform.Rotate(Vector3.left * rotationSpeed * Time.deltaTime);
}
}
}

Related

How do i get one object to track and move towards another object

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyControler : MonoBehaviour
{
private Transform player;
// Start is called before the first frame update
void Start()
{
//Note in this case we're saving the transform in a variable to work with later.
//We could save the player's game object (and just remove .transform from the below) but this is cleaner
var player = GameObject.FindWithTag("Player").transform;
}
// Update is called once per frame
void Update()
{
//**** The code below you need to modify and move into your own method and call that method from here.
//**** Don't overthink it. Look at how Start() is defined. Your own Move method would look the exact same.
//**** Experiment making it private void instead of public void. It should work the same.
//How much will we move by after 1 second? .5 meter
var step = .5f * Time.deltaTime; // 5 m/s
var newPosition = Vector3.MoveTowards(transform.position, player, step);//This is one way to move a game object by updating the transform. Watch the videos in this module and it should become apparent what goes here.
}
}
The transform does not map to the tagged player. I was trying to get an enemy in unity to move towards a moving player for a class, but I'm completely lost.
You had three issues in your code. The first was that you were defining a new player variable in the Start method. This hid the player member field you defined earlier.
The second issue was that you were getting a value to move towards, but you weren't assigning that value to the current objects position.
The third issue was that you were feeding in a Transform into the MoveTowards method, when you should have been feeding in a Vector2.
The code below should rectify these issues.
public class EnemyControler : MonoBehaviour
{
private Transform _player;
void Start()
{
_player = GameObject.FindWithTag("Player").transform;
}
void Update()
{
var step = .5f * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, _player.position, step);
}
}
Try doing something like this ive used this in the past to do something similar once you understand the code change it to what you desire
public int minRange;
private Transform target = null;
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
target = other.transform;
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "Player")
target = null;
}
void update()
{
transform.LookAt(target);
float distance = Vector3.Distance(transform.position,
target.position);
bool tooClose = distance < minRange;
Vector3 direction = tooClose ? Vector3.back : Vector3.forward;
if (direction == Vector3.forward)
{
transform.Translate(direction * 6 * Time.deltaTime);
}
else
{
transform.Translate(direction * 3 * Time.deltaTime);
}
}

Struggling in Unity 3d object Controls

I'm totally new to Unity and game development...I made a 2D object of the car that can move to 8 directions....each direction with the specific animation of the car's movement...Now, how do I make my car move in such a way that if it's moving straight LEFT it shouldn't go immediately straight to RIGHT when turning RIGHT, so I want it to make a proper round turn or a "U TURN" to move towards its opposite direction and obviously the same with UP and DOWN turns....can anyone please help me in at least one way I can fix this?
or the other way to ask this question would be if I'm moving my object to x = -1 direction then on turning to x = 1 it should first go through x = 0 and then x = 1 so that it looks like a turn.
this is the code for my CAR so far..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CARmovement : MonoBehaviour
{
public float speed;
private Rigidbody2D myRigidbody;
private Vector3 change;
private Animator animator;
private Vector3 lastMoveDirection;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
change = Vector3.zero;
change.x = Input.GetAxis("Horizontal");
change.y = Input.GetAxis("Vertical");
UpdateAnimationAndMove();
}
void UpdateAnimationAndMove()
{
if (change != Vector3.zero)
{
MoveCar();
animator.SetFloat("moveX", change.x);
animator.SetFloat("moveY", change.y);
animator.SetBool("driving", true);
}
else
{
animator.SetBool("driving", false);
}
}
void MoveCar()
{
myRigidbody.MovePosition(transform.position + change * speed * Time.deltaTime);
}
}
I try an example of rotating a car. We add an object (here I add a car as an example), select the object (car) to create a C# Script script, double-click to open, we define two variables Speed_move, Speed_rot to control the movement speed and Rotation speed and assign values to them. We use Translate to control the forward and backward movement of the cube through the W and S buttons, forward with forward, and back with back; use Rotate to control the rotation of the object through the A and D buttons, up is the Y-axis rotation. The following is the code for the specific rotation.
if (Input.GetKey(KeyCode.W))
{
this.transform.Translate(Vector3.forward * Time.deltaTime * Speed_move);
}
if (Input.GetKey(KeyCode.S))
{
this.transform.Translate(Vector3.back * Time.deltaTime * Speed_move);
}
if (Input.GetKey(KeyCode.A))
{
this.transform.Rotate(Vector3.up * Time.deltaTime * -Speed_rot);
}
if (Input.GetKey(KeyCode.D))
{
this.transform.Rotate(Vector3.up * Time.deltaTime * Speed_rot);
}

Update breaks function in Unity

I have the following code
public Rigidbody2D rb;
public float speed = 5f;
void FixedUpdate()
{
if (Input.GetKeyDown("w"))
{
Fire();
}
}
void Fire()
{
rb.MovePosition(rb.position + Vector2.down * speed * Time.deltaTime);
}
but every time I play the game, the ball does not move according to the fire function, it only goes down by 1 on the y-axis.
How can I edit my code, so that the Rigidbody moves according to the Fire() function?
There could be a couple things going wrong here. The first thing that stands out to me is that you're using Input.GetKeyDown instead of Input.GetKey-- GetKeyDown only returns true on the first frame that the key is pressed (so it's useful for things like shooting once per keypress), whereas GetKey returns true for the entire time that the key is down (so it's useful for things like movement). Changing that should give you the behavior that you're expecting.
Another issue is that you're doing input checking in FixedUpdate. It runs on a separate game loop from Update, and you can find more details about that here: Is it really wrong to use Input.GetKey() on FixedUpdate?
I would use Input and GetKey to store the input state in a Vector2 in the Update loop, and then use that data in FixedUpdate to do the actual movement:
public Rigidbody2D rb;
public float speed = 5f;
private Vector2 velocity = Vector2.zero;
void Update()
{
if (Input.GetKey("w"))
{
velocity = Vector2.down * speed;
}
else {
velocity = Vector2.zero;
}
}
void FixedUpdate()
{
MoveBall();
}
void MoveBall()
{
rb.MovePosition(rb.position * velocity * Time.deltaTime);
}
This way, you also have a stronger separation between the input code and movement code, and it will be easier to handle once you start trying to implement more complexity. Good luck!

Firing Projectiles in the same direction as my character is looking. [UNITY 2D TOPDOWN]

I've searched through a bunch of posts on Top Down 2D rotation with firing missiles and none of them apply to mine.
My Wizard manages to fire his magicmissiles from his wand but they come out unaligned with his wands direction. It should be taking the Z value from the Quaternion of the wand and assigning that as the angle it goes out in ( or atleast thats what i believe it should be doing) But it seems to rotate faster than the wand and whilst it does change if I spin it isn't changing equally with the wand. So whilst if I point up it will fire up. If i point 45 degrees right of that it fires the missile directly into my wizard.
The Code for the MissileMovement ---------------
using UnityEngine;
using System.Collections;
public class MoveMissile : MonoBehaviour {
// Use this for initialization
public float speed = 0.5F;
public Transform Shotspawn;
// public Quaternion Direction;
private float Direction;
void Start (){
// Sets the direction that shot is fired in.
Direction = transform.rotation.eulerAngles.z;
transform.Rotate(0 , 0, Direction);
}
// Update is called once per frame
void Update () {
transform.Translate(Vector2.up * speed);
}
}
The Code for the Character Movement ---------------------------
using UnityEngine;
using System.Collections;
public class TopDownCharController2 : MonoBehaviour {
// Movement Variables
public float walkSpeed;
public bool colliding;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
if(Input.GetKey (KeyCode.I))
{transform.Translate(Vector2.up * walkSpeed); } // UP MOVEMENT
if(Input.GetKey(KeyCode.J))
{transform.Translate(-Vector2.right * walkSpeed); } // LEFT MOVEMENT
if(Input.GetKey(KeyCode.K))
{transform.Translate(-Vector2.up * walkSpeed); }// DOWN MOVEMENT
if(Input.GetKey(KeyCode.L))
{transform.Translate(Vector2.right * walkSpeed); }// RIGHT MOVEMENT
if(Input.GetKey(KeyCode.U)) {
// Clockwise
transform.Rotate(0, 0, -3.0f);
}
if(Input.GetKey(KeyCode.O)) {
// Counter-clockwise
transform.Rotate(0, 0, 3.0f);
}
}
}
If anyone could show me where i'm going wrong that would be lovely. :)
So the reason it doesn't work is because it reads the direction and then adds a bit more to it so it sort of over corrects. So the code should read:
using UnityEngine;
using System.Collections;
public class MoveMissile : MonoBehaviour {
// Use this for initialization
public float speed = 0.5F;
public Transform Shotspawn;
void Start (){
// Sets the direction that shot is fired in.
transform.rotation=Shotspawn.rotation;
}
// Update is called once per frame
void Update () {
transform.Translate(Vector2.up * speed);
}
}

Issues with a script that should follow another GameObject's position

I currently have a little issue with a script I made. Basically, I want to create a script that makes its GameObject (let's name it A) and follows another GameObject's (named B) position. I know a simple way to do that would be to parent A to B, but I'm not doing it for two reasons :
1) I want to be able to apply a smoothing (whose value I can change) on A's movement;
2) I want to be able to make A follow B's position and/or rotation at will.
Here is the script I wrote :
using UnityEngine;
using System.Collections;
public class FollowGameObject : MonoBehaviour {
public GameObject m_GameObjectToFollow;
public bool m_FollowPosition;
public bool m_FollowRotation;
public float m_PositionSmoothing;
public float m_RotationSmoothing;
// Should not be changed once set
public bool m_UseOffsetPosition;
public bool m_UseOffsetRotation;
private Vector3 m_PositionOffset;
private Quaternion m_RotationOffset;
void Start () {
m_PositionSmoothing = Mathf.Clamp(m_PositionSmoothing, 0.0f, 1.0f);
m_RotationSmoothing = Mathf.Clamp(m_RotationSmoothing, 0.0f, 1.0f);
if (m_UseOffsetPosition)
{
m_PositionOffset = transform.position - m_GameObjectToFollow.transform.position;
} else {
m_PositionOffset = Vector3.zero;
}
if (m_UseOffsetRotation)
{
m_RotationOffset = transform.rotation * Quaternion.Inverse(m_GameObjectToFollow.transform.rotation);
} else {
m_RotationOffset = Quaternion.identity;
}
}
void FixedUpdate () {
if (m_FollowPosition) {
Vector3 goalPosition = m_GameObjectToFollow.transform.position + m_PositionOffset;
transform.position = Vector3.Lerp(transform.position, goalPosition, m_PositionSmoothing);
//transform.Translate(newPosition - transform.position, Space.World);
}
if (m_FollowRotation) {
Quaternion goalRotation = m_GameObjectToFollow.transform.rotation * m_RotationOffset;
transform.rotation = Quaternion.Lerp(transform.rotation, goalRotation, m_RotationSmoothing);
}
}
I hope the code is easily understandable, if not feel free to ask.
In any case, once I attach this script to A and assign its m_GameObjectToFollow attribute to B (B is parented to a character controller, and I parented a sphere renderer to A so I can see if it follows B correctly), I notice that A is indeed following B, but I see that its position (through the sphere renderer) is "fluctuating" between the "right" position (B's) and another one. Visually, the sphere is flickering.
I tried putting the smoothing values to 1 (i.e. A should always be at B's position/rotation). I still see a flickering.
Could someone explain to me what I did wrong?
EDIT : Seems like I'm using Lerp the wrong way with its last value. I modified the script to use speed values instead of smoothing values, but still the same problem when I try to create some smooth movements (with lower speed values).
I have troubles explaining the problem properly. The best way to see what the problem look like would be to experience it yourself :
1) Create a scene with a terrain and a character controller in it;
2) Parent the main camera to the controller (so that it always follows it);
3) Create a new GameObject with a renderer (for example, a sphere), not parented to any other GameObject, but attach the following script to it :
using UnityEngine;
using System.Collections;
public class FollowGameObject : MonoBehaviour {
public GameObject m_GameObjectToFollow;
public bool m_FollowPosition;
public bool m_FollowRotation;
// Betzeen 0 and 1. 1 means that a complete unsmoothed follow
public float m_PositionFollowSpeed;
public float m_RotationFollowSpeed;
// Should not be changed once set
public bool m_UseOffsetPosition;
public bool m_UseOffsetRotation;
private Vector3 m_PositionOffset;
private Quaternion m_RotationOffset;
void Start () {
if (m_UseOffsetPosition)
{
m_PositionOffset = transform.position - m_GameObjectToFollow.transform.position;
} else {
m_PositionOffset = Vector3.zero;
}
if (m_UseOffsetRotation)
{
m_RotationOffset = transform.rotation * Quaternion.Inverse(m_GameObjectToFollow.transform.rotation);
} else {
m_RotationOffset = Quaternion.identity;
}
}
void Update () {
if (m_FollowPosition) {
Vector3 goalPosition = m_GameObjectToFollow.transform.position + m_PositionOffset;
transform.position = Vector3.Slerp(transform.position, goalPosition, Time.deltaTime * m_PositionFollowSpeed);
}
if (m_FollowRotation) {
Quaternion goalRotation = m_GameObjectToFollow.transform.rotation * m_RotationOffset;
transform.rotation = Quaternion.Slerp(transform.rotation, goalRotation, Time.deltaTime * m_RotationFollowSpeed);
}
}
}
With :
m_GameObjectToFollow = the character controller GameObject;
m_FollowPosition = true;
m_PositionFollowSpeed = 10;
(The other parameters values don't matter for this test)
Now start the scene and move the character controller, I will see the sphere flickering during motion, but if you stop moving it will smoothly go to the controller.
You are using FixedUpdate. Is there any special reason to do so?
Anyway, try to use Update or LateUpdate instead of FixedUpdate or check Fixed Timestep in Project Settings => Time.
Also read the answer to this question for more information about difference between Update and FixedUpdate.

Categories

Resources