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.
Related
I have my editor camera and I'd like to spawn objects where it is looking, as well as it is done by unity when primitives are Instantiated.
As I understand the title of your questions you want to raycast from the scene view camera against the global XZ axis which passes through the world origin and place an object at the hit position.
To find the "editor" or better said the SceneView camera you can use SceneView.camera.
var camera = SceneView.camera;
Then for creating a ray from it use either Camera.ScreenPointToRay e.g. if you want to take the mouse position into account
var ray = camera.ScreenPointToRay(Input.mousePosition);
or simply the cameras Transform.forward vector
var ray = new Ray(camera.transform.position, camera.transform.forward);
Or alternatively if you are calling this from within Editor.OnSceneGUI you could also use HandleUtility.GUIPointToWorldRay
var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
Then for raycasting against the global XZ plane you can use a mathematical Plane
// Creates a XZ plane going through world origin
var plane = new Plane(Vector3.up, Vector3.zero);
Then you can raycast against it using Plane.Raycast
if(plane.Raycast(ray, out var distance)
{
var hitPoint = ray.GetPoint(distance);
// Spawn your object and set its position to hitPoint
}
I found the solution to my problem but in the end I don't need to do that.
To answer to your questions :
Please be more specific on what exactly you try to achieve .. e.g. spawn in front of > exactly which camera? And "in front" how far away?
I needed to instantiate my robot Prefab at the intersection of the XZ plane and the Raycast shot from the editor's view camera no matter how far it is.
And yeah I managed to make it work as Hugo saidin his previous answer.
I have a laser turret in Unity3D, which I'd like to turn towards the enemies. The turret consists of a "leg" and a "head" (selected on the picture 1). The head can pan and tilt around a spherical joint.
I do the following:
Vector3 targetDir = collision.gameObject.transform.position - turretHead.transform.position;
float step = turnSpeed * Time.deltaTime;
Vector3 newDir = Vector3.RotateTowards(turretHead.transform.forward, targetDir, step, 0.0f);
turretHead.transform.rotation = Quaternion.LookRotation(newDir);
The problem is that since the pivot of the head is not aligned with the laser beam, the turret turns into the almost right direction, but it shoots above the target. (It would hit perfectly, if the laser would come out of the red axis of the pivot.)
Is there a builtin method or some trick to achieve the correct functionality other then doing the calculation myself?
Okay, here's the quick and easy way to do this. It's probably "better" to do it with proper trig, but this should give you the result you want pretty quick:
If you don't already have a transform aligned with the barrel, then create an empty GameObject and line it up (make sure it's a child of the turret so they move together). Add a reference to your script for it's transform.
Then, in your first line, calculate from the new Barrel transform instead of the turretHead transform. Leave everything else the same. This way it calculates from the turret barrel, but moves the turret head.
Now, this approach isn't perfect. If the pivot center is too offset from the barrel transform, then it would be less accurate over large moves, or when aiming at something close by, because the expected position when aiming would be different than the initial position due to the rotation pivot being elsewhere. But this can be solved with iteration, as the calculation would become more accurate the closer it is to it's desired goal.
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 want to change the floor's vertex normals' direction as the ball is rolling on the floor. I just need some direction on how to achieve this.
So far this is the direction that I'm heading:
Make a copy of all the vertex normals of the floor on start.
On collision get the contact point and raycast/spherecast/boxcast to get the affected vertices. (Set variable offset to control how much vertices I want to be affected by the casting)
Find normals related to the vertices.
Rotate the affected normals parrallel to the ball's closest surface point.
As ball moves away from affected's floor's vertices, slowly return the floor normals back to original direction. (Set a variable to control the movement speed of the normal's rotating back to original direction)
I just need help figuring out which type of casting to use and how to rotate the normals parallel to the ball's surface. This is for a mobile platform so performance is a must.
Thanks in advance.
Here's how you'd go about modifying the normals:
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
Vector3[] normals = mesh.normals;
You'd want to use the vertices list to figure out which indexes to modify (presumably also needing to convert from local space to world space). You could then raycast from the worldspace coordinate to the ball's center,1 and use the raycasthit.normal to figure out what the angle to the ball is.
Some clever vector math from there to figure out the new normal for your plane:
Find the vector perpendicular between hit.normal and Vector3.Up: this vector will be parallel to the plane. If the two vectors are parallel, dump out: your normal is unchanged (or should be returned to its original value, which will be the same vector as the raycast to find the sphere).
Find the vector perpendicular to that vector and hit.normal: this vector will be your new normal.
1 Actually, you'll want to know how far down from the ball's center you should target, otherwise, you'll get the most extreme offsets as the ball moves farther away from the plane. So you want the ball's position on X and Z, but a fixed offset up from the plane for Y. This won't be too difficult to calculate.
I would try something like:
Create a texture for the normals. Each pixel is a normal of a vertex(like a grid). Calculate the correspoding coord between the 3d ball and the position of the normal in the texture and draw a ball/circle/sprite on it (like a sprite) each frame. Then you could use a compute shader to revert them slowy to the default up vector.
I am writing the enemy class of a 3d game I am making and am working on making the enemy follow the player. I want the enemy to basically rotate itself in the direction of the player a little bit every frame and move forward a bit every frame. I tried to use Lerping to accomplish this as seen in the code below, but I can't seem to get it to work. When playing, the enemies don't even appear in my field of view or chase me at all. Here is my code from my enemy class below.
Note: p is a reference to a player object that I am chasing, world is the enemy object's world matrix, quaternion is this enemy object's quaternion.
My current strategy is finding the direction vector in between the forward vector of my enemy and the location vector3 of the player and then lerping that by an amount determined by the velocity variable. Then, I try to find the perpendicular vector to the plane determined by the enemy's forward vector and that new lerped vector I call midVector.Then, I update my quaternion for the player to be rotated about that perpendicular vector. Here is the code below:
//here I get the direction vector in between where my enemy is pointing and where the player is located at
Vector3 midVector = Vector3.Lerp(Vector3.Normalize(world.Forward), Vector3.Normalize(Vector3.Subtract(p.position,this.position)), velocity);
//here I get the vector perpendicular to this middle vector and my forward vector
Vector3 perp=Vector3.Normalize(Vector3.Cross(midVector, Vector3.Normalize(world.Forward)));
//here I am looking at the enemy's quaternion and I am trying to rotate it about the axis (my perp vector) with an angle that I determine which is in between where the enemy object is facing and the midVector
quaternion = Quaternion.CreateFromAxisAngle(perp, (float)Math.Acos(Vector3.Dot(world.Forward,midVector)));
//here I am simply scaling the enemy's world matrix, implementing the enemy's quaternion, and translating it to the enemy's position
world = Matrix.CreateScale(scale) * Matrix.CreateFromQuaternion(quaternion) * Matrix.CreateTranslation(position);
//here i move the enemy forward in the direciton that it is facing
MoveForward(ref position, quaternion, velocity);
}
private void MoveForward(ref Vector3 position, Quaternion rotationQuat, float speed)
{
Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotationQuat);
position += addVector * speed;
}
My question is both, what is wrong with my current strategy/implementation and is there an easier way for me to accomplish this (the first part is more important)?
You aren't storing your object's orientation from frame to frame. I think you are thinking that the quaternion you are creating is oriented in the objects new direction. But actually, it's just a quaternion that only represents the rotational difference between last frame and the current frame, not the overall orientation.
So what needs to happen is your new quat has to be applied to last frame's orientation quaternion to get a current frame orientation.
In other words, you are creating an inter-frame update quaternion, not the final orientation quaternion.
You need to do something like this:
enemyCurrentOrientation = Quaternion.Concatenate(lastFrameQuat, thisNewQuat);
There's probably is an easier way but if this way's working for you, no need to change it.