I am creating a program using Unity3D in which the player fires an arrow at a target. What is the best way to ensure that the arrow is flying through the air at a rotation which depends on it's angle of movement? (ie the arrow head is facing upward of ascent and downward on descent)
I've had a look at the transform.LookAt and Quaternion.lookRotation functions I'm but now sure how they can apply. Here's the code which dictates the arrows velocity:
newArrow.GetComponent<Rigidbody>().velocity = new Vector3 (5*(transform.position.x - mousePos.x), 10*(transform.position.y - mousePos.y), 0);
Set the constraints on the rigidbody. In your case it should only rotate around the x axis so that it aims up and then down.
For the rest, you just set the initial rotation on throw:
newArrow.transform.rotation = Quaternion.LookRotation(velocity);
This may need some tweak based on your model initial orientation.
Related
I'm new to 3D design, so this might be a silly question.
I have trouble simulating wheel camber using rotation with Quaternion.
What I understand is that the rotation of the WheelCollider occurs along the X axis, whereas in my case the "visual wheel" is rotated 80 ° along the Z axis so the rotation occurs along the Y axis.
This code works well with the FL wheel because its axis is aligned with the collider axis, while it doesn't work with the FR wheel.
collider.GetWorldPose(out Vector3 position, out Quaternion rotation);
visual.transform.position = position;
// initialVisualRotation is the wuaternion rotation of the visual at Startup
// in this case: X=0 Y=0 Z=80
visual.transform.rotation = initialVisualRotation * rotation;
These are my local and global rotation axes for the right front wheel (FR).
How can I "adjust" the wheel rotation without change initial axes (as I did for the FL wheel)?
Are there some quaternion operations to adopt in these cases?
A bit of workaround for not having to deal with messed up transforms is to make object a child of another empty object.This way you can make parent object rotated to make wheel tilted but Child( actual wheel) will have its original axis always not messed with and so you can use simple script to always rotate it around same axis that is always going to be the same despite whole system(hierarchy of objects) being " tilted".
Parent is responsible on rotating around one axis and child around another.
I think you need to take a step back and arrange your prefabs this way as it seesm you did not.
I'm trying to make a character that walks around a platform and if the character reach a corner, it rotates and continue walking on the side of the platform, same with the bottom part.
This is a visual representation of what I'm trying to achive.
Movement
The specific problem is when the character reach the corners, the rotation just go crazy. I'm trayng to achive this using a raycast from the character to the platform and if the raycast doesn't find floor, I start the rotation like this:
times++;
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.AngleAxis(times*-89.9f,Vector3.forward),Time.deltaTime * RotationSpeed);
_characterGravity.SetGravityAngle(transform.localEulerAngles.z);
I'm using a characterGravity script that allows me to change the gravity direction for the character in order to not fall when is walking upside down or on the sides. But this is not working propperly. Is there a better way to do this?
Assuming your 2D view is aligned on the X-Y plane, with the Z-axis aimed into the screen (the same direction the camera is facing), I suggest using Transform.Rotate() instead of trying to linearly interpolate the rotation between two values:
if (ShouldRotateAroundCorner()) {
transform.Rotate(Vector3.forward, RotationSpeed * Time.deltaTime);
}
You'll just need to make sure your ShouldRotateAroundCorner() knows when to start and stop the 90 degree turn, which will take a little bit of additional code to keep track of when it's in this state change.
I started some programming in Unity just for fun a couple days ago.
So far my game (pretty much top-down shooter) consists of player flying in an asteroid field, in which lurk enemy ships. Player can shoot down asteroids and enemies, and enemy ships have missile turrets that "track" player.
Everything works fine until I decided that enemy ships shouldn't be able to rotate their turrets all the 360-way. Think of it as real-world battleship being unable to turn it's front turret (No.1) 180 degrees behind because turret No.2 is in the way.
Currently code for turret rotation is like this (this is not about making "gradual rotation", setting "rotation speed" or something, so please don't look at that!):
playerTarget = GameObject.FindGameObjectWithTag("Player");
chaseDirection = Quaternion.LookRotation(playerTarget.transform.position - transform.position);
newYaw = Mathf.Clamp(chaseDirection.eulerAngles.y, minYaw, maxYaw);
transform.rotation = Quaternion.Euler(0, newYaw, 0);
That works okay, until player flies behind enemy ship. As soon as player gets into turret's "possible rotation angle", it just snaps past "dead zone" to new direction if I don't turn it gradually with fixed angle, or is still stuck trying to rotate "past limit" until target (player) flies all around enemy ship so the angle to target is small enough for rotation direction to be calculated through "enabled" rotation zone, not through "dead zone".
An important thing is I am not looking for answer "how to make gradual rotation". I am looking about calculating rotation direction!
I thought about coding enemy to start rotating turret in counter-direction as soon as player passes "directly behind" the turret "forward facing" position. But the concept of how to do that eludes me.
Because as soon as turret rotates just a bit from limit, it's able to turn "towards" player again, and gets stuck at limit again.
Edited with the clarification in mind.
You need a function that will tell you if you should rotate clockwise or counter-clockwise, based on the enemy location.
First find the mid point, this will be:
var mid = (minYaw + maxYaw) / 2
In your example this will be 3 o'clock, straight right.
Now, if your current rotation is lower than mid, and the target is higher than mid, than you must rotate clockwise even if it's not the shortest rotation to get there.
If the target rotation is higher than mid, and the target is lower than mid, you must rotate counter-clockwise for the same reason. You may need to adjust for negative degrees.
Please note that this will create a secondary effect, where once the ship passes the half point of the dead zone (say moving from 10 o'clock to 8 o'clock in your example), the turret will start moving as if anticipating the flank. You may want to disable this movement in a special case.
I'll keep the second part of my answer as-is, for future references.
If you want it to move gradually, you need to use deltaTime or fixedDeltaTime in case of a fixed update. You can define how fast it will move by adding a speed property. Try something like this:
void update () {
var playerTarget = GameObject.FindGameObjectWithTag("Player");
var chaseDirection = Quaternion.LookRotation(playerTarget.transform.position - transform.position);
var newYaw = Mathf.Clamp(chaseDirection.eulerAngles.y, minYaw, maxYaw);
var currentRotation = transform.eulerAngles;
var desiredRotation= currentRotation;
var desiredRotation.y = newYaw;
transform.eulerAngles = Vector3.RotateTowards(currentRotation, desiredRotation, Time.deltaTime * RotationSpeed, 0.0f);
}
I created 2 cylinders and put one on top of the other. Then I clicked to simulate physics and on each cylinder I added the following image blueprint, added a 50-point rotation on the z axis of each cylinder in opposite directions.
It turns out that in the simulation, when I perform, the cylinders rotate in one direction and move on the ground in the other direction. If it turns clockwise it moves left, and vice versa, and should be the other way around.
Can anyone help me solve this? It's for both cylinders to work together and I see how their simulation is accelerating with a constant rotation, but that's not what happens
If you want to simulate physics you should be applying forces to the cylinders using Add Torque in Radians or Add Torque in Degrees rather than modifying the rotation directly.
Alternatively, if you want to precisely control the cylinders, do not simulate physics. Instead, disable Simulate Physics and animate the rotation and position of the cylinders directly as you are.
I have a finger object. It is just three cubes representing the finger parts.
The 2nd cube is the child of the 1st one. And the 3rd cube is the child of the 2nd one.
This is the heirarchy: Cube1 -> Cube2 -> Cube3
My goal is to apply a rotation angle to the first cube and let the other cubes do the same locally.
Example: Apply 30 degrees Z rotation to the first cube, 30 degrees Z rotation to the 2nd cube, and also the 3rd one.
This will make a finger that look like this:
(Forgive me if it doesn't look like a finger)
In every Update() frame, I will change the angle (it's just one number) and it will rotate every cube for me.
My question is:
How do I make all these cubes collide properly with other objects?
I tried putting the Rigidbody on all of them and set isKinematic=false because I want to transform them myself. But I still cannot use transform.rotation to update my rotation because it will miss the collision with a ball very easily (especially the tip of the finger because it moves faster than other parts). Continuous detection doesn't help.
So I tried using rigidbody.MoveRotation() and rigidbody.MovePosition() instead, which is a pain because they need absolute values. They worked but the animation is so jumpy when I change the angle quickly.
I'm guessing that the animation is jumpy because there are many Rigidbodies or because the physics engine cannot interpolate the position of each box properly when I use MoveRotation() and MovePosition().
I need to use MovePosition() also because when I use only child.MoveRotation(transform.parent.rotation * originalChildLocalRotation * Quaternion.Euler(0, 0, angle)), the position doesn't move relative to the parent. So I have to compute child.MovePosition(parent.TransformPoint(originalLocalPositionOfTheChild)) every frame too.