In Unity3D, I'm working on simply controlling a ball. My goals are as follows:
Allow the ball to rotate
Move in the direction the ball is facing
Ensure the ball is visually rotating as the ball is moving
What I am attempting to do is almost accomplished with this character controller script I wrote:
transform.Rotate (new Vector3(-Input.GetAxis ("Horizontal") * rotationSpeed, 0, 0));
Vector3 forward = Input.GetAxis ("Vertical") * transform.forward * moveSpeed;
controller.Move (forward);
controller.SimpleMove (Physics.gravity);
My problem with this script is that the ball does not visually "roll".
I attempted to solve this by using a Rigidbody:
float movementHorizontal = Input.GetAxis("Horizontal");
float movementVertical = Input.GetAxis("Vertical");
Vector3 movementVector = new Vector3(movementHorizontal, 0.0f, movementVertical);
GetComponent<Rigidbody>().AddForce(movementVector * moveSpeed * Time.deltaTime);
But in this case, you are unable to rotate anymore then 180 degrees using WAD like the first example. Although it does solve the visual problem.
How is it that I can allow my ball to rotate with the "A" and "D" keys, and then go in the direction the ball is facing with "W" while also visually rotating?
Take a look a this example:
http://unity3d.azurewebsites.net/Labyrinth/
move the ball with the arrow keys
move the camera with the keypad (#5 will chase)
zoom in/out with - + keys
change perspective with V key
The code behind the movement is here:
https://github.com/heldersepu/hs-unity/blob/master/Labyrinth/Assets/Movement.cs
Related
I'm kind of new in learning Unity scripting and currently i'm writing a script where by pressing the Space key together with A or D key would do some sort of a "dash" movement by rotating faster.
In the gif below I show the basic A and D movement without dashing movement. What i've done is that i've put an empty with the script and an object parented to the rotating empty.
the example
What I wanted to do is that whenever the player wanted to go faster on a direction, it would "dash" on the left by pressing A+Space and on the right by pressing D+Space. I kind of managed to do this thing with this code (where rotSpeed is the rotation speed and dashAmount is the speed added to make the "dash"):
transform.Rotate(dashAmount + rotSpeed * Time.deltaTime, 0f, 0f);
Of course, this worked but the cube would just teleport instead of "dashing" smoothly to the left or right. Then i found out about Quaternion.Lerp but the code i wrote doesn't really work correctly (destinationRot is the final rotation and dashSpeed is set to 0.8f)
if ((Input.GetKey(KeyCode.Space)) && (Input.GetKey(KeyCode.D)))
{
Quaternion destinationRot = Quaternion.Euler(transform.rotation.x + dashAmount, 0f, 0f);
transform.rotation = Quaternion.Lerp(transform.rotation, destinationRot, Time.deltaTime * dashSpeed);
}
How can I fix this?
Hello all, I'm very new to and very confused by Unity.
I'm creating a top-down, gravity-free test game, similar to PacMan (i.e. think of the movement of characters in straight lines).
Currently, I'm trying to move an object in straight lines (without curvature) (see image).
My GameObject has RigidBody2D attached, as well as Linear, Angular and Gravity set to 0.
I'm currently controlling my GameObject by adding force:
private Rigidbody2D _playerRB2D;
public float _speed;
private void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector2 movement = new Vector2(moveHorizontal, moveVertical);
_playerRB2D.AddForce(movement * _speed);
}
The idea is that the game object won't get to slow down, so is constantly in motion (in straight lines). Collision with objects is obviously important too!
Any help or information to look at will help a lot, thank you!
Unity has a built-in physics engine that calculates movement based on velocity (and collisions, etc.) By using Rigidbody2D.AddForce, you are adding to your rigidbody's velocity. This means that if you press the up arrow and then the right arrow, the velocity from pressing the up arrow remains, causing a diagonal velocity and curved path. If you want straight lines, you can use Rigidbody2D.velocity or just use Transform.translate.
_playerRB2D.velocity = movement * _speed;
Edit: You said that collisions were important, so keep the rigidbody
or remove the rigidbody2D component and use
transform.Translate(movement * _speed);
The idea is basically to reset the force being applied on the rigidBody2D on each changed direction.
In fact, you would have to test if the direction input from horizontal is greater than vertical for x axis, and the inverse for y axis , and thus if it is true, change the opposite to 0f.
You would have normally:
Vector2 movement = new Vector2(moveHorizontal < moveVertical ? moveHorizontal: 0f, moveVertical < moveHorizontal ? moveVertical: 0f);
_playerRB2D.velocity = movement * speed;
Edit: By testing the input value, you can move your RigidBody2D with a analogic controller, and thus being straight as you wished !
I'm working on this tank game where you move a tank using the keyboard input and aiming its turret using the mouse input.
For the tank movement I use this code in the update method:
x = Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed;
z = Input.GetAxis("Vertical") * Time.deltaTime * speed;
transform.Rotate(0, x, 0);
transform.Translate(0, 0, z);
But I get results similar to this video (even when locking the rotation of the axes):
https://streamable.com/tm33b
Is there anyway to prevent such irritability with the movement of the tank, also is there anyway to attach both the body and the turret of the tank while making each rotate independently, also the tank to climb the terrain appropriately.
I'm a beginner to unity, I'm sorry if my questions were obvious or easy. I will be so thankful if I get any direct solution to this.
Note that both Translate and Rotate have a last optional parameter Space relativeTo = Space.Self. This means by default always Space.Self is used:
If relativeTo is left out or set to Space.Self the movement is applied relative to the transform's local axes. (the x, y and z axes shown when selecting the object inside the Scene View.) If relativeTo is Space.World the movement is applied relative to the world coordinate system.
Your tank opject starts "flying" and "tilting" because you rotate and translate in its own local coordinates instead of world coordinates. You should instead use
transform.Rotate(0, x, 0, Space.World);
transform.Translate(0, 0, z, Space.World);
to perform the translate and rotate in workd space.
I'm working on a 2D game in Unity. I have some GameObjects which should move into the direction of the player.
On start I flip the transform.forward vector into the direction of the player.
Vector3 target = new Vector3(player.transform.position.x, transform.position.y, transform.position.z);
transform.right = (target - transform.position).normalized;
In the editor I can see that the transform.right vector (red arrow) is pointing in the right direction. But when I move the gameobject it moves in the wrong direction if the gameobject is right from the player.
rBody.AddForce(Vector2.right * movementSpeed);
And I have no idea why? Has anyone any suggestions? Thank you.
You're using AddForce() which always uses global space in reference to your character. You want to use local space to append your force, so use AddRelativeForce().
Try:
rBody.AddRelativeForce(Vector2.right * movementSpeed);
https://docs.unity3d.com/ScriptReference/Rigidbody.AddRelativeForce.html
Changing Vector2.right into transform.right solved my problem
rBody.AddForce(transform.right * movementSpeed);
I have the following code to clamp player movement. It works but i have a problem. For example if the player is at position -3.05 and if I hold the button to move left the player still moves over the -3.05 limit to about -3.56. Once i let go of the button it bounces back to -3.05. Same goes for the right side. I do not want it to go over the limits no matter what.
Vector3 tmpPos = transform.position;
tmpPos.x = Mathf.Clamp(tmpPos.x, -3.05f, 3.05f);
transform.position = tmpPos;
The following is the way i add movement to the player:
rigidbody.AddForce (movement * speed * Time.deltaTime);
You should not mix up transform operation with rigidbody unless it's marked isKinematic. So instead of transform.position, try clamping rigidbody.position inside of FixedUpdate.
void FixedUpdate(){
Vector3 pos = rigidbody.position;
pos.x = Mathf.Clamp(pos.x, minX, maxX);
rigidbody.position = pos;
}
However, since you're using AddForce to move your object, a much simpler way is to make empty game objects with box collider on the left and right of the object, which then will limit your object movement like invisible walls.
Try using rigidbody.MovePosition(tmpPos); instead of setting transform.position.
I solved my problem. Instead of using the AddForce to move the object
rigidbody.AddForce (movement * speed * Time.deltaTime);
I use rigidbody.position to move the object. I use Mathf.Clamp to limit the movement before applying it to rigidbody.position.