I have a cube which i want to move always on the surface of the mesh. Like i have a destination on the surface where player want to go but it should go to the destination without leaving the mesh. Like it go along the surface of the mesh. I know that i Can move towards the destination like this:
IEnumerator MoveToDirection(Vector3 startPosition, Quaternion orientation, Transform planet)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.rotation = orientation;
go.transform.position = startPosition;
while (true)
{
go.transform.position= go.transform.position + go.transform.up * Time.deltaTime* speed;
yield return new WaitForEndOfFrame();
}
}
But don't know how to restrict that it should not leave the surface of the mesh.
There are 3 ways to achieve this effect:
Use physics: attach rigid body/collider to cube/mesh and use something like AddForce
Add every frame move cube to target and calculate position in runtime. If you have formula to calculate height (for example, if you mesh generated from noise or it just sphere) - you can use formula, in other case you can add MeshCollider to mesh and RayCast touch point of mesh/cube every frame + correct cube position
If mesh not endless you can use Unity Nav Mesh system - it will be easiest way to solve complex tasks.
Related
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.
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 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.
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'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.