in unity editor, when i enable "Pivot", gameobject will rotate around "pivot point" position, when i enable "Center", gameobject will rotate around "center point"
but if i use script to rotate, it always rotate around "center point", for ex, here is my scene:
I use following code:
void Start()
{
// transform.rotation = Quaternion.Euler(new Vector3(0, 0, 90));
transform.RotateAround(transform.position, new Vector3(0, 0, 1), 90);
}
it rotate around "center point"
if object has collider, i can get pivot point with colider.bounds, if not, how should i do?
and even worse, in some case, i hope rotate to like set rotate in unity editor inspector, i use following code:
transform.rotation = Quaternion.Euler(new Vector3(0, 0, 90))
I have no idea to adjust above code to rotate around pivot point
update
I think if i can "rotate", i can also impl "rotate to", so the key point is, how should i get "pivot point" that is used in RotateAround, to object has collider, I can get with colider.bounds with transform.position, to no collider object, how should i do?
The pivot point is the-same as the transform.position you're already using. If you don't like where the pivot point is or the location the rotation is rotating against, you have two options:
1. Create new empty GameObject. Move it to the position you want your GameObject to rotate around. Once satisfied by that location, make this new GameObject a child of the GameObject you will be rotating around. Use the position of this new GameObject as the pivot rotation point for the transform.RotateAround function.
Drag the empty GameObject to the customPivot slot in the script below. That should give you a new pivot point to rotate your GameObject around.
public Transform customPivot;
void Update()
{
transform.RotateAround(customPivot.position, Vector3.up, 20 * Time.deltaTime);
}
2. Open a 3D application and change the pivot point of your object, then save and re-import it into Unity.
Since this is just used to rotate object around, I suggest #1. If the problem is that the pivot point is not centered, I would suggest #2.
Related
I am working on a monogame project in which the player controls a ship in space (first person) and shoot asteroids that are spawned at random locations with random velocity. When I shoot, I want to place my bullet object 1.5 units directly in front of my camera no matter where the camera is or which direction it is facing. I have tried this line
Vector3 torpedoPos = CameraPosition + CameraDirection * 1.5f;
as these two posts suggest: Placing objects right in front of camera, Placing an object in front of the camera, but as soon as my position is anything other (0, 0, 0) the object is placed in the same location no matter what direction I am facing. In the line of code I posted, torpedoPos is the position I want to spawn my bullet object, CameraPosition is the current position of the camera object in 3d space and CameraDirection is a unit vector with the direction the camera object is facing.
I solved this issue with this line of code
Vector3 torpedoPos = CameraPosition + Vector3.Transform(Vector3.Forward, Orientation * 1.5f);
The orientation is the matrix which holds which direction my ship is facing. By doing a transform with the orientation * 1.5 and Vector3.Forward, I get an amount to add to my current position that will place the torpedo directly in front of the ship.
So in my Unity exercise, I have to rotate a GameObject to face away from where I clicked my mouse. Also, I can only rotate around the Y-axis i.e. the GameObject is only allowed to rotate either purely to the right or purely to the left, and cannot tip towards the ground at any point. Also, I've got to do this without RayCasting (I've already done it WITH RayCasting, so as an exercise, I've got to do it without). Here's the code I've written after multiple attempts but it doesn't seem to be effective enough:
Vector3 clickLocation = Input.mousePosition;
Vector3 clickWorldLocation = Camera.main.ScreenToWorldPoint(new Vector3(clickLocation.x, clickLocation.y, transform.position.x)); //the transform.position.x is just to add some depth
transform.LookAt(new Vector3(clickWorldLocation.x, transform.position.y, clickWorldLocation.z), Vector3.up);
This code works fine if my GameObject remains in its starting position, but fails if I move it to another location and attempt the same action. Could someone help me out please?
First, call Camera.main as infrequently as you can, as it uses an expensive operation (FindGameObjectsWithTag) and doesn't cache the result.
private Camera mainCamera;
void Awake()
{
mainCamera = Camera.main;
}
To answer your question, don't use ScreenToWorldPoint in this situation, because a depth isn't most easily calculated. You don't have anything meaningful to use for the z component, and transform.position.x makes no sense here.
Instead, create a Plane that you want to click into (such as the plane parallel to the view plane and intersecting the object), use ScreenPointToRay to turn the mouse position into a Ray, then find where the ray and plane intersect. Plane.Raycast is much, much faster than a physics raycast. Then, find the direction from the mouse world position to the object, and use Quaternion.LookRotation to turn that direction into a rotation you can assign to the object's rotation:
Ray mouseRay = mainCamera.ScreenPointToRay(Input.mousePosition);
Plane mousePlane = new Plane(mainCamera.transform.forward, transform.position);
float rayDistance;
if (mousePlane.Raycast(mouseRay, out rayDistance))
{
Vector3 mouseWorldPos = mouseRay.GetPoint(rayDistance);
// make the z component of mouseWorldPos the same as transform.position
mouseWorldPos.z = transform.position.z;
Vector3 awayFromMouseDir = transform.position - mouseWorldPos;
transform.rotation = Quaternion.LookRotation(awayFromMouseDir, Vector3.up);
}
In my game I want the character to be able to have a pickaxe or weapon that can rotate around the player but when I do so it goes through the objects and is very glitchy.
I want it to still follow the mouse (which is invisible) and still stop when it has a collision. My code right now is just pretty standard code for mouse rotation and its attached to an empty gameobject which is the parent of the pickaxe/weapon
//rotation
Vector3 mousePos = Input.mousePosition;
mousePos.z = 5.23f;
Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);
mousePos.x = mousePos.x - objectPos.x;
mousePos.y = mousePos.y - objectPos.y;
float angle = Mathf.Atan2(mousePos.y, mousePos.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
Whenever you have a GameObject that you want to be physics enabled, you don't move it directly. You add a Rigidbody and use RigidBody.MoveRotation to rotate your GameObject. RigidBody has its set of movement and rotation methods that take into account collisions. Moving the Transform directly will cause problems.
This can still cause problems in some situations. If you're still experiencing physics weirdness then you can eliminate them by using a "physically correct" solution and use Rigidbody.angularVelocity. Based on the angle you can set the velocity to either rotate the object right or left until it faces the way you want.
Essentially the physics system hates teleportation. Instant movements and instant rotations are basically teleportation to it. So there's a hierarchy of how "physics system friendly" some actions are. And they go like this:
Adding Force to the RigidBody
Adding Velocity to the RigidBody
Moving the GameObject through appropriate RigidBody methods.
Moving the GameObject through Transform.
How to Roll/rotate the cube on it's edge?(Like this)
I read a couple of articles and answers to the questions but still not what I need.All I learned ,is that I need to create a gameobject in the center of the Cube and 4 others on the pivots.Something like that
And what's next, should I use Quaternions or transform.Rotate?Is the hierarchy correct?
I was about to tell you to use an external 3D software to set the pivot point to the location in your screenshot but it looks like you want to do this with multiple pivot points so you will to use empty GameObjects to accomplish this.
From your screenshot, you seem to be on the right track.
1.Create empty GameObjects and position them in the edges you want to rotate the cube around then place them under the cube.
2.Use transform.RotateAround not transform.Rotate to rotate the cube. The first parameter should be the edge pivot point. The second parameter is the axis you want to rotate the cube against. The third one is the angle.
//cube to rotate
public GameObject cube;
//Assign dge pos from the editor
public Transform edgePivotPoint;
public float rotSpeed = 60f;
void Update()
{
cube.transform.RotateAround(edgePivotPoint.position, Vector3.back, rotSpeed * Time.deltaTime);
}
Note, if rotating the wrong way, try replacing Vector3.up with Vector3.down, Vector3.left, Vector3.right, Vector3.forward and Vector3.back. The one to use depends on your scene setup but trying them will get you to the one
I'm using my camera as a child gameobject of my ball, so when I move my ball camera comes with him. But the problem is I'm using rigidbody.addForce(), so when ball rotates the camera rotates with it, too.
So what should I do not to rotate my camera but only move it with my ball?
void FixedUpdate()
{
rigidbody.addForce(Input.getAxis("Horizontal"), 0, Input.getAxis("vertical"));
}
There are several ways to solve this, I'll list a few.
The first, if you don't care if your ball rotates or not, you can just disable the rotation on the ball. If you open the Constraints section in the rigidbody component, you can freeze the rotation so that the ball won't rotate.
Alternatively, you can write a script that keeps the camera always oriented a certain way. Depending on if you want the camera to rotate around the ball on any plane depends on the way you would implement this.
The third option, which is cleanest, is to not have the camera be a child of the ball. A minimal component to do this would look like this:
public class TargetFollow : MonoBehaviour
{
public Transform Target;
public float DistanceFromTarget;
void Update()
{
transform.position = Target.position + new Vector3(0, 0, DistanceFromTarget);
transform.LookAt(Target);
}
}
Just drag your ball into the 'Target' slot in your component. Keep in mind, this is super bare bones. You may want to add more variables to better control the direction the camera should be from the ball, or perhaps something that grabs a snapshot of the direction and distance the camera is from the ball in the Start method.