Unity 3D move object around orbit with user inputs - c#

I have a spaceship which flies around planets orbit by this script:
Update() {
transform.RotateAround(planet.transform.position, Vector3.up, speed * Time.deltaTime);
}
But I don't understand how to add user inputs (Input.GetAxis("Horizontal") and Input.GetAxis("Vertical")) to this script so user can control spaceship's movement. How can I move spaceship around orbit using user input (arrows) ?
EDIT:
Camer follows ship from behind. Ship is moved forward by some force (speed) on planet's orbit (to simplify, it's just a circle). I want user to be able to change direction of movement (left\right) like in the pucture (from D1 to D2).

This task can be split into two parts. First is rotating the ship based on user input. The second is to change our method of orbiting to account for the rotation of the ship so that it moves in the direction that it is facing.
We can solve part one by using a Transform.Rotate call. Since we want the bottom of the ship to always face the planet, we want to rotate along the ship's "Up" axis. For our Input axis, the "Horizontal" will likely be the most intuitive. It will look something like this:
transform.Rotate(Vector3.forward, Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime);
For part two, it is important to realize that Transform.RotateAround uses the world space, and not the local space. By making it use the local space of the ship, it will account for the ship's rotation such that the ship will move in the direction that it is facing, rather than moving in an independent direction. We can do this by using the Transform.TransformDirection function. It will look something like this:
transform.RotateAround(planet.transform.position, transform.TransformDirection(Vector3.up), speed * Time.deltaTime);
Combining these in an update function worked for me in a quick test.
In addition, if we want the ship to strafe from side to side without doing any local rotation of the ship, we can do it with another Transform.RotateAround call, like so:
transform.RotateAround(planet.transform.position, transform.TransformDirection(Vector3.right), Input.GetAxis("Horizontal") * strafeSpeed * Time.deltaTime);
(Answer edited for question edit)

Related

Have an object follow a line I draw

I want to make my character jump by drawing lines.
But while my code is going towards the x-axis direction in 2D, when I switch to 3D, it always turns upwards regardless of the direction of the line. There is no change in the X-axis. My code is as follows:
if (other.gameObject.CompareTag("Line"))
{
rb.AddForce(Vector3.up * speed * Time.deltaTime, ForceMode.Impulse);
/ / Destroy(other.gameObject);
}
Could someone suggest how to correct my code?
Currently you're passing in Vector3.up as the force's direction, meaning that the character will always jump straight up.
If you want the character to jump in the line's direction, maybe try using the line's transform to send the player the right way, like this:
if (other.gameObject.CompareTag("Line"))
{
Vector3 jumpDir = other.gameObject.transform.up;
rb.AddForce(jumpDir * speed * Time.deltaTime, ForceMode.Impulse);
}
Now you'd need to point the "Line" GameObject in the direction you want the player to jump when they collide. (In the scene view, the Line transform's green arrow should be the character's jump direction)
You could switch it to the red or blue arrows (x or z axes) with
jumpDir = other.gameObject.transform.right;
or
jumpDir = other.gameObject.transform.forward; respectively.
You need to get the direction depending on the line you drew.
Depending on how you implemented your lines, you can get the directions from the transform via
Transform.up
Transform.forward
Transform.right
If you need the other directions, you can simply invert the Vectors.
Also you don't need to use Time.deltaTime while using rb.AddForce(), because the physic-system is taking care of it.

How to use transform.forward that only acknowledges one axis of rotation?

I am making a rolling ball game, and the way I want it to work is based on constant forward movement and rotation based turning.
I'm using force, which then has the ball roll forward.
My Issue here is that I would like the ball to move forward based on where it's "facing". Using Vector3.forward only moves it according to world space and transform.forward will start going backwards because the ball rolls over, upside down.
How can I make it so transform.forward ignores my forward turning, only being effected by the sideways turning?
"forward" is hard to imagine on a sphere.
You add speed when rotating around the X-axis (ball moves "forward")
For direction control, you rotate around global Y-axis.
The transform.forward will spin around the object. But the transform.right (local x-axis so to say) stays stable.
So we only need the Vector3.Cross Product of the transform.right and the global Vector3.Up.
Vector3 forward = Vector3.Cross(transform.right, Vector3.up);
You can use vector math for this. Take the cross product between the local right and the world up:
private static Vector3 GetRollingForward(Vector3 localRight)
{
return Vector3.Cross(localRight, Vector3.up);
}
// ...
void Update()
{
Debug.DrawLine(transform.position, transform.position
+ GetRollingForward(transform.right));
}

Unity CharacterController always moves in the same direction independent from rotation

If i'm rotating my player on the Y-Axis and move it like
transform.Translate(Vector3.forward * Time.deltaTime)
it will move along the Z-Axis of the character (as expected).
If I used CharacterController.Move it will always move in the same direction, independent from its rotation.
How can I make the player follow it's rotation?
The problem is that you are translating the character forward on a global level. This means forward will always be in the same direction. Instead, use transform.forward. That way, you are translating the player on the forward vector on the player.
Another way to do it is using transform.rotation * Vector3.forward. This will rotate the global forward by the rotation of the player, returning the same thing as transform.forward.

Set direction of rotation Unity C#

I am trying to make a spin wheel that is divided into 6 sections. Each section is marked with a gameObject that is centered in that section. After the player spins the wheel, it will rotate until its starts stopping and then the wheel moves and stops in the center based on the section that was selected (Randomly). I used the following code to rotate the wheel towards the 0 on X axis. this code works fine and the wheel rotates fine, but only if the selected section was on the positive X axis.
float rotateFloat = (((randomReward + 1) * 60) - 30) - transform.rotation.z;
Quaternion targetRotation = Quaternion.Euler(new Vector3(0, 0, rotateFloat));
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, f_difX * Time.deltaTime);
I did some digging and found that Quaternion.RotateTowards()finds the closest way towards the target and rotates using that direction (This caused a problem with the direction of rotation).
Example (Follow image): The player swipes and randomReward (Number 5 on spin wheel) and the wheel starts rotating. When the wheel slows down, it starts moving towards the center. Then it will stop spinning along the direction of the swipe and will rotate towards the other side (Because the distance to the center is closer from the left side).
How can I set it to follow the same direction of the swipe regardless of which is closer to the center. And maybe if there is a better way to do this, please enlighten me. Thanks.
I think the easiest way to rotate a GameObject is by using:
float Speed = 1f;
void Update()
{
// Rotate the object around its local X axis at 1 degree per second
transform.Rotate(Vector3.right * Time.deltaTime * Speed);
}
You can read more about his here
It can happen sometimes the center of the GameObject it´s not placed in the center of the mesh or sprite. If you can´t modify this for any reason, what you can do is place this model/sprite as a child of an Empty GameObject and then attach the rotation script to the Empty GameObject.
While i understand that you don't want people to rotate the disk to the reward they want. Why do you use a random reward and go through the trouble of lining the rotation to the reward?
You should be able to say catch a 'swipe time', then do some math to it (say so it turns at least once if the screen touch time is very short) and then add a random range to it, that is within the circumference of the disk. Then when the disk is done spinning do a ray cast at the top location to determine the reward? (could also link the spinning time to the swipe-time, so that the reward is offered in somewhat the same time interval).
//this comment would have been made as a comment if i would have had the rights to do so, as i think this response may help the question asker, it is provided as an answer instead. i do hope this doesn't piss any one off to much :(

Display Object in front of player without considering its rotation

I can show another object in front of my player using this simple line of code
newPosition =player.transform.position+player.transform.forward * distance
but how can i restrict it to always show in the same position(but in front of player) no matter what is the rotation of my player?
When you rotate gameobject transform.forward always changes.Because of you are using local values. But you need the use word values for this.
newPosition =player.transform.position+Vector3.forward * distance

Categories

Resources