How to do panning in Unity? - unity3d

I am a beginner in Unity and I created a 3D app in Unity.
For rotate, I'm rotating the camera around the 3d model.
For pan, if I move the 3d model, I've to keep a track of the coordinates (x,y,z). But if I move the camera, since LookAt() is implemented in the rotate function, it doesn't look like the pan gesture is executed (while shifting from rotating and panning).
Can someone please suggest a solution for this problem?

If you want to pan with the object, you can do so using vector mathematics.
Example:
new Vector3 lookAt = ...;
new Vector3 offset = ...;
cameraTransform.LookAt(lookAt + offset);
if you want to change between the motions of panning and rotation, you can use a statemachine for that.
switch (state)
{
case CHANGEPAN:
// do something
break;
case CHANGEROT:
// do something
break;
}
whilst panning, if you don't want to rotate the camera at all, you'll need to do an equivalent translation to the cameras position. You can do that also with vector mathematics, since position in the transform is just a Vector3.

Related

How to make a 3D compass in Unity? similar to the transform compass in scene mode

I'm trying to make a 3D compass in unity, like the one in scene mode.
But its not looking to bright.
At the moment
end goal How do I better emulate the scene mode transform compass? and keep the GamObject "3DCompass" always in view? (without putting it under the Main Camera)
//Compass3D
public class Compass3D : MonoBehaviour
{
public Vector3 NorthDir;
public Transform Player; // Camera
public GameObject NorthLayer;
// Update is called once per frame
void Update()
{
ChangeNorthDir();
}
public void ChangeNorthDir()
{
NorthDir.z = Player.eulerAngles.y; //May need to change
NorthLayer.transform.eulerAngles = NorthDir;
}
}
Hm...
Well, firstly, you need to realize that the compass' orientation never changes. That's kind of the point of it. The compass always points the same way, meaning it doesn't rotate.
Meaning there's no need for you to do anything in update, you just set where the north is supposed to point to, and leave it at that. The illusion of it rotating comes from person rotating, while the compass keeps pointing the same (global) direction.
The second thing is a big, lazy, awesome secret I'm going to tell you about:
Quaternion.LookRotation
So what you need to do is just rotate the compass correctly on Start, meaning rotate it so that its "Forward direction" is Vector3.forwards (that's a global Z+), and its upward is Vector3.up (global y+). And then never touch the rotation again.
But you want it to stay in view (without being childed to the camera), so what you'll do in update is that:
public class Compass3D : MonoBehaviour
{
public Vector3 NorthDir;
public Transform Player; // Camera
public Vector3 offsetFromPlayer; //needed to keep position from camera. this basically determines where on screen the compass will be positioned. 0,0,0 would be at the same position as the camera, experiment with other values to find one which positions compass relative to camera in such way that it displays on screen where you want it
public GameObject NorthLayer;
void Start()
{
//northDir can be whatever you want, I'm going to assume you want it to point along Unity's forward axis
NorthDir = Vector3.forward;
//set the compass to point to north (assuming its "N" needle points in the direction of model's forward axis (z+). if not, change the model, or nest it into a gameobject within which you'll rotate the model so that the N points along the parent gameobject's z+ axis
NorthLayer.transform.rotation = Quaternion.LookRotation(NorthDir, Vector3.up);
//nothing else needed, the rotation will be fine forever now. if you want to change it later, just do the above line again, and supply it the new NorthDir
}
// Update is called once per frame
void Update()
{
//only thing you need to do in update, is keep the relative position to camera. tbh, easiest way would be to parent the compass, but you said you don't want that, so...
transform.position = Player.position + (Player.rotation * offsetFromPlayer);
//you need to make sure that the compass' offset from camera rotates with the direction of the camera itself, otherwise when camera rotates, the compass will get out of view. that's what multiplying by Player.rotation is there for. you rotate Vectors by multiplying them with quaternions (which is how we express rotations).
}
}
What this code does: first it sets the compass so it points towards north. And then it never touches that again, because once the compass points towards north, if it's not parented to anything (which I assume it's not), it will keep pointing north. IF it is parented to anything else, just copypaste that line from start to Update too, so that when the orientation of compass' parent changes, the compass fixes its pointing back to global north.
Then, in update, it only updates its position, to keep at the same place relative to camera. The important thing to note is that the position needs to take the camera's direction into account, so that when camera rotates, the compass moves similarly to if you had your hand outstretched in front of you, and you rotated your whole body. If the compass is not parented to anything, that motion the tip of your hand does is still just a position change, but it is position relative to your whole body and its direction, so that position change needs to take that into account.
In this code, if you put the offsetFromPlayer as Vector3(0,0,1), that would mean "one unit along the way the camera is looking". If you put it as Vector3(1,0,1), that would mean "one unit along the way the camera is looking, and one unit to the right". So you'll need to experiment with that value to find one that makes the compass display where you actually want it to be on the screen.

Unity Question: Transforming world coordinates to my Radar's Coordinates for 3D Radar

I'm learning Unity3D and having some trouble on my 3D radar. My radar is a child of my Player game object which is rotating around as I fly. The radar itself is rotated 45 degrees so it faces the user. There is a Cube that is supposed to be the radar blip of the enemy plane. The Cube is a child of Radar so should inherit its rotation. There is a script on the Cube to update itself every update(). Here is the hierarchy:
Enemy Plane
Player
-- Camera
-- Radar
------ Cube (radar representation of Enemy Plane)
The problem is that while the Cube itself is rotated, with the Radar, its motion is not. As I get closer to the enemy plane, the Cube just gets closer to the camera (which is good) but I would expect its motion to follow the 45 degree rotation of the parent Radar object?
public class RadarGlyph : MonoBehaviour
{
GameObject radarSource;
GameObject trackedObject;
Vector3 radarScaler;
void Start()
{
this.radarSource = GameObject.Find("Radar");
this.trackedObject = GameObject.Find("Enemy Fighter");
this.radarScaler = new Vector3(0.001f, 0.001f, 0.001f);
}
void Update()
{
Vector3 vDelta = this.trackedObject.transform.position - this.radarSource.transform.position;
vDelta.Scale(this.radarScaler);
this.transform.localPosition = this.transform.InverseTransformDirection(vDelta);
}
}
For a complete solution, you have to get the position of the target wrt the ship first and then recreate it within the context of the blip and the radar.
As a quick fix, you can try changing your last line like this:
this.transform.localPosition = this.parent.localRotation * this.transform.InverseTransformDirection(vDelta);
or (apparently not good as you mentioned)
this.transform.localPosition = Quaternion.Inverse(this.parent.localRotation) * this.transform.InverseTransformDirection(vDelta);
one of these is bound to work. (The first one did)
Edit: here's a third alternative
this.transform.localPosition = this.transform.parent.parent.InverseTransformDirection(vDelta);
This one gets the position in Player's space and applies it in radar's space.
The first and third are trying to do the same thing. Since you were transforming the direction into the blip's coordinate frame, any rotations that its parents have are canceled out. Instead, the correct thing to do is to get the position relative to the Player first. Then apply it to the blip in the radar. The third line of code I have here is attempting to do that.

How do I apply rotations to parent child using Rigidbody?

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.

Unity3D rotate GameObject to face direction of travel

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.

How to change gravity direction on Sprite Kit?

I am using Sprite Kit in Xcode and I was wondering how to change gravity direction.As default gravity direction to "X" you can imagine on below axes graphic.What about if I would like to change to "Y".
My goal is giving to object the falling effect.Its like falling from hight point and touching the ground than getting respond with physics!
(Could be dices on board game)
//Default gravity direction is X
SKSpriteNode *myNode =[SKSpriteNode spriteNodeWithImageNamed:#"ball"];
myNode.physicsBody=[SKPhysicsBody bodyWithCircleOfRadius:self.frame.size.width/2];
[self addChild: myNode];
Thanks in advance!
You can apply a vector to the Physics World of your scene using this code
self.physicsWorld.gravity=CGVectorMake(0,-10);
In SpriteKit, X and Y are the default coordinates that you see on the screen, and the Z coordinate is the order in which the objects are positioned (the zPosition). Since SpriteKit uses a 2D game engine, you do not have a third dimension, Z, to utilize. You can change the gravity between Y and X (Top/Bottom and Left/Right of screen respectively), but not between the Z coordinate. If you want to recreate a "dice falling" effect, I would recommend you create a Sprite called Dice scaled to a large amount, and once you add it to the scene you scale it down in x amounts of seconds.
[self runAction:[SKAction scaleBy:negativeFloatHere duration:3]];
This will make the dice appear to be falling, and you might want to add some spinning animations for it if you with. If you want to use the 3D engine, go try out Metal or SceneKit