I'm making a unity 3D game, part of the game allows the player to get into a car and drive it.
Inside the car I have put a "seat" GameObject whose position and rotation is used to determine where the player will sit.
When I want the player to sit in the car, I make the car the players parent, then set the player transform position and rotation to that of the seat.
Here is the C# code
// make player's parent the same as the seats parent (which is the car)
transform.parent = seat.transform.parent;
// put player in the exact position and rotation as the seat
animator.transform.position = transform.position = seat.transform.position;
animator.transform.rotation = transform.rotation = seat.transform.rotation;
animator.transform.localPosition = transform.localPosition = seat.transform.localPosition;
animator.transform.localRotation = transform.localRotation = seat.transform.localRotation;
This seems like it should work, but what ends up happenning is that for some reason the player does not end up perfectly in the seat, but some short distance away from it, and also the players rotation doesnt match the seat, instead ends up slightly off. So the player looks like he is not really in the seat but floating near it, and turned around in some other direction.
Anybody knows what I'm doing wrong?
position specifies an object's location in the world. If you take two objects and assign the same position, then they will both be in the same place.
localPosition specifies an object's location relative to its parent. If you take two objects and assign the same localPosition, the outcome will depend on the position of each object's parent. If they have different parents, different scaling, or different rotation, they may end up in different places.
Roughly the same idea applies to rotation and localRotation.
You seem to have confused the relationship between world-space and local-space coordinates. It's very important to understand the difference, and how they relate to the scene hierarchy.
If you want to put both objects in the same place, this should suffice:
transform.position = seat.transform.position;
transform.rotation = seat.transform.rotation;
If you want the object to move with the car, afterward, you could also reassign its parent:
transform.parent = seat.transform.parent;
Check your player object's pivot point.It might not be on position you expect.If it is not, try to make it point where you want by dragging your model.
Related
I have an object and a player. How do I make it so that the object is always in front of the player, no matter what position the player is at?
Hey guys thanks for your replies! Just to add that the object spawns at a random position, then I have made it move towards the player (this is why I haven't made it a child of the player). From then it will always stay in front of the player.
You can set that object to be a child of the player
GameObject childPlacehoderObj; // Set this to the child you want to give a home
GameObject playerObj; // This will be the parent
childPlacehoderObj.transform.parent = playerObj.transform;
Now the child will move along with the parent.
Update: object spawns at a random position, then I have made it move towards the player
What you can do then, is to create an empty object which will be the final position of that object. And this empty object you make it a child of the player.
Then what you do is to make the object, one it is spawned, to move to the position of that empty object. You can add something like this in the object which should be in front of the player
void Update()
{
// Move our position a step closer to the target.
float step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, childPlacehoderObj.position, step);
}
Finally once the object reaches the target point, you can make it child of the player.
Maybe you could just set the player as parent of the Object. Like this the Object would define it's Position after the Position of the Player and after it is once infront of the Player it would always stay there no matter his postition.
I am trying to position my gun the way most fps games position it,
for example like this:
But I'm having a problem when I try to position and rotate it with the player. The gun doesn't rotate well and doesn't have the same position always.
Is there a way to keep a gun in the same position and make it rotate well with the player?
But my main problem is the position of the gun i need it to stay in one place like in every fps, when i start the game and pick a gun it spawn in diffrent location on the screen Because of the rotation.
Here's is the code that I am trying to use:
GameObject temp = GameObject.Find(gameObject.name);
playerGuns[keyPress] = Instantiate(temp, Player.transform.position
+ new Vector3(-2f, 3f, 4f), Quaternion.identity) as GameObject;
playerGuns[keyPress].name = gameObject.name;
playerGuns[keyPress].tag = gameObject.tag;
playerGuns[keyPress].transform.parent = Player.transform;
playerGuns[keyPress].transform.rotation.SetLookRotation(Player.transform.position);
Alright here is the answer I promised:
First issue was with how you were setting your rotation, SetLookRotation takes in 2 parameters, Vector3 view, and Vector3 up the second is defaulted to Vector3.up. You were passing in the player.transform.position, for the "view" which is the direction you want transform to look in. Think of it like this, if I am far east facing west, my weapon will face east... (That is assuming the SetLookRotation normalizes it.) this is because my actual position is east, from some arbitrary origin. Something you could have used would have been player.transform.forward.
To spawn an object and have it have the same relative rotation and and position you can use Instantiate like you have in your original code. There are Several versions of instantiate.
In the comments I said to give yourself an offsetPosition and a eulerAngle, but this can be quite troublesome if you have multiple weapons. I mentioned I would give a recommendation for how I would set this up for multiple weapons... So here yea go.
Scriptable Objects,
In Unity you can create this objects to store information about a particular object, so for example a "Weapon" object can look like this:
using UnityEngine;
using System.Collections;
[CreateAssetMenu(fileName = "New Weapon", menuName = "Weapon")]
public class WeaponObject : ScriptableObject {
public string objectName = "New Weapon";
public Vector3 offSetPosition;
public Vector3 startOffsetRotation;
public float fireRate;
// Using a gameObject to store the weapon model so you can technical
// store the firing point.
public GameObject weaponModel;
}
You can create a new object now by right-clicking in your asset directory and going to create->weapon. Once you have done this you can rename the object it made, and the inspector will show all the public fields for this object you can modify.
With this you can create multiple weapons, and store their data in like a WeaponManager, that spawns every weapon. with something like:
WeaponObject weapon = WeaponManager.getWeapon(keyPress);
playerGuns[keyPress] = Instantiate(weapon.weaponModel, Player.transform.position + weapon.offsetPosition, Quaternion.identity) as GameObject;
playerGuns[keyPress].name = weapon.objectName;
playerGuns[keyPress].transform.parent = Player.transform;
playerGuns[keyPress].transform.eulerAngles = weapon.startOffsetRotation;
if(player.weaponScript != null) {
// we can have a single script for all of our weapons, and the WeaponObject
// will control its firerate, which projectiles it fires, etc.
player.weaponScript.setWeapon(weapon);
}
playerGuns[keyPress].transform.parent = Player.transform;
This line might be causing a problem. If you are parenting your gun to the players transform then it will follow the player. But it sounds like you want it to follow the camera?
try:
playerGuns[keyPress].transform.parent = Camera.main.transform;
Here is a useful answer provided by reddit user Mathias9807:
Many games will clear the depth buffer before drawing the gun model.
This will prevent the gun model from clipping through geometry but it
can look a bit weird when standing near a wall:
If you just want to render an object sticking to the camera you should
just get rid of the view matrix (Assuming you're using model-, view-
and projection matrices).
Explanation: Normally when you are using a view matrix (the camera matrix),the objects in the scene are being translated relative to the magnitude of the cameras position vector, and rotating by its yaw and pitch, which gives the illusion of a camera moving in a 3D space, but really there is no camera, just the objects in the scene that scale, and translate in in relation to the values defined for the camera.
So, when you remove that camera matrix for an object, the cameras position now has no influence on the models position, or put another way, the model does not move relative to the camera anymore but moves congruently with the camera.
I need to know if there is an established way to do this, given that what defines screen boundaries depends on the device, etc. I have these rigid bodies that are not kinematic and not affected by gravity with light masses. When I instantiate them, they are all in an empty with a sphere overlapping them to create an "explosion" effect.
This works well, however after the sphere pushes the rigid bodies apart and explosion has occurred, I need the bodies to ALL keep moving until out of the users view/the screen. This happens for most of them but they are some stragglers and some take a very long time, staying in center of the screen.
I would normally apply a force but I do not know for each rigid body (there are a lot) which way they would need to move depending on where they are.
How can I apply a force that gets all these rigdibodies off the screen? The explosion is supposed to be in all directions. Is there a certain Vector that would do this?
Project the position of the object onto the camera's facing vector. And then make a vector from the projected point, back to the object.
So, something like..
var t = Vector3.Dot(Camera.main.transform.forward, obj.transform.position); //distance along view vector
var p = Camera.main.transform.position + Camera.main.transform.forward * t; // position along view direction
var d = obj.transform.position - p; //vector from center to object
Plane object position to Plane GameObject position.
Basically I've created a plane based on three points. But, for testing reasons I need to know where the Plane is. So, I've got a Plane GameObject (that comes with a mesh, texture, and all the other things that come with it) in my Hierarchy. I want to move the Plane GameObject to the position and the normal to be that of the Plane object.
Here's some of the code:
plane1Go = GameObject.Find("Plane1");
Plane plane1 = new Plane(Point1,Point2,Point3);
plane1Go.gameObject.GetComponent<Mesh>().vertices= new Vector3[4]{Point1,Point2,Point3,Point4};
As you can see I use the three points, used to make the Plane object to move the Plane GameObject.
First thing, the Plane GameObject does not move and I don't know why.
Second and more importantly, I want to use the Plane object to actually be the point of reference for the Plane GameObject.
Unless it has changed, you should be modifying the Transform element of the gameobject.
GameObject.FindWithTag("PlaneTop").transform.position = new Vector3(10, 0, 0);
This maintains the mesh, but moves the object.
The reference point for the GameObject itself depends on where the local space origin of the mesh is placed when the mesh is exported. I'm not entirely sure what you are trying to achieve but it may be a case of repositioning the mesh itself, rather than the game object.
I'll suggest a two-step approach:
Position a GameObject on the plane
Make that GameObject face in a direction equal to the plane's normal
I assume that you have a mesh attached to the GameObject, perhaps a big quadrilateral of some sort.
Plane plane = new Plane(point1, point2, point3);
//technically, any point on the plane will work
//for our purposes, I'll take the average of your three inputs
Vector3 center = (point1 + point2 + point3) / 3f;
//find the plane's transform
Transform planeTransform = GameObject.Find("Plane1").transform;
//position the plane
//then make it face toward its normal
planeTransform.position = center;
planeTransform.LookAt(planeTransform.position + plane.normal);
The second part of your question is less clear:
I want to use the Plane object to actually be the point of reference for the Plane GameObject.
You could reposition planeTransform as often as needed. You could reposition it each time the plane changes, or once per frame in an Update function.
I do recommend caching the results of GameObject.Find if you're going to be calling this a lot.
I currently have an item placement system for building. It works by instantiating a "ghost" of the object that shows where it can be placed, the ghost (semi-transparent) object is attached to the camera and instantiates the object in its place when the player clicks.
I get the position at which to keep the ghost object like so:
var pos = transform.position + transform.forward * placeDistance; // A position 'someDistance' in front of the player
pos.y = Terrain.activeTerrain.SampleHeight(pos); // Get the position at the surface of the terrain to place the object
firePlaceable.transform.position = pos + Vector3.up * 0.001f; // 'halfHeight' is used in case the pivot is not on the base
Now.. I need the object to rotate according to the terrain so that the fire place is placed more or less correctly rotated. Any ideas? What would the best plan be?
Use the terrain normal vector at the place' position.
For example you could do a raycast straight down from the fireplace. The resulting hit contains a normal that is your place' up vector.
By thinking of it... I assume you already doing a raycast to get the position to place the fireplace right?
Use the placement raycast to get the up vector instead of making a new one.
So basicly do
fireplace.transform.up = clickPlaceHit.normal;