I create a scene in unity. I add camera and 3d unity cube object to the scene. To move object to mouse click position, I add raycast and it works.
But I want to use my model. I have an obj and mtl file. I copy them to Assets folder. I use below code. The object moves but not exact my click position.
Plane plane = new Plane(Camera.main.transform.forward, transform.position);
pos = Input.mousePosition;
Ray ray = Camera.main.ScreenPointToRay(pos);
float dist;
if (plane.Raycast(ray, out dist))
{
Vector3 v = ray.GetPoint(dist);
objectPos = v;
}
transform.position = objectPos;
Origin of model is not (0,0,0). I cut this object from a big 3d model.
I try to move to (Screen.width/2, Screen.Height/2, 0.0f) and result is below
EDIT
EDIT 2
I add box collider to object. But the collider position is not same as the object.
You have to move the null point of the object or save a variable which is representing the vector by which it has to be moved and add it to the objectPos befor setting the transform.position
Related
I have rawimage inside a game object and want to move it by drag and drop but must not exceed parent gameobject
I can move the raw image but It can go anywhere in the canvas
for that I calculate the border points and allow it if it stays in border but mouses eventdata.position gives world position.
how can I transform mouse position to position in game object?
You can translate the mouse position to world position then world position to local position
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 objectRelative = object.transfrom.InverseTransformPoint(mousePos);
Another approach is to use collider bounds, these aren't always super accurate however, depending on the shape of your object
In your child object's update method, make sure you have [ExecuteInEditMode] at the top of your script
if(!Application.isPlaying){
Vector3 minBounds, maxBounds;
Collider parentCollider = transform.parent.gameObject.GetComponent<Collider>();
minBounds = parentCollider.bounds.min;
maxBounds = parentCollider.bounds.max;
float xPos = Mathf.Clamp(transform.position.x, minBounds.x, maxBounds.x);
float yPos = Mathf.Clamp(transform.position.y, minBounds.y, maxBounds.y);
float zPos = Mathf.Clamp(transform.position.z, minBounds.z, maxBounds.z);
transform.position = new Vector3(xPos,yPos,zPos);
}
I am using unity AR foundation image tracking. When a tracked picture appears on the screen, how can I get its position or its relative distance to the camera?
You can get the distance from the camera to the picture by giving the camera position and the game object transform position of the identified picture. I'm currently using this in one of my apps and its working nicely.
Vector3.Distance(pictureGameObject.transform.position, Camera.main.transform.position)
well you would need the position of that other object to check the Distance. This can be done by using Vector3.Distance.
First however you need the Transform of the other object. You can do this by making a Raycast, in this case I'm casting the raycast from the middle of the screen. Then I will assign the Transform of whatever object was hit to the hitTransform variable. After that I can use a Vector3.Distance to compare 2 positions and calculate the distance.
Transform hitTransform;
private float distance;
void Update()
{
Ray ray = cam.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
RaycastHit hit
if (Physics.Raycast(ray, out hit))
{
hitTransform = hit.transform;
}
distance = Vector3.Distance(hitTransform.position, transform.position);
}
So in short, if you look at an object that is in the middle of the screen the distance between that object and the camera will be in the distance variable, you can also use a raycast when you click or press a button but for the sake of simplicity I used the middle of the screen for this.
I have a script attached to a mesh with a kinematic, rigid body with a convex mesh collider that I'd like to move around. Here's what I call in my update function:
if (Input.GetKey(forwards)) {
Debug.Log("forwards!!");
//get current velocity in local space
Vector3 localVel = transform.InverseTransformDirection(body.velocity);
//alter so that forward component = speed
localVel = new Vector3(localVel.x, localVel.y, linearSpeed);
//convert back into world space and set to body
Vector3 worldVel = transform.TransformDirection(localVel);
body.velocity = worldVel;
}
Other Info:
body is a Rigidbody variable that I assign in Start() using GetComponent<Rigidbody>();
linearSpeed is a float with value 1
I'm getting the Debug.Log output, but my mesh is not moving. Is there anything obvious I'm missing here? This is my first script for a 3D, as opposed to a 2D game.
public float speed = 20;
Rigidbody r;
void Start(){
r = gameObject.GetComponent<Rigidbody> (); //Put's reference to local rigidbody into variable "r"
}
void FixedUpdate () {
Vector3 direction = Vector3.zero; //set's current direction to none
//Adds vectors in case that user is pressing the button
if(Input.GetKey(KeyCode.W)) direction += Vector3.forward;
if(Input.GetKey(KeyCode.S)) direction -= Vector3.forward;
if(Input.GetKey(KeyCode.D)) direction += Vector3.right;
if(Input.GetKey(KeyCode.A)) direction -= Vector3.right;
//Normalizez direction (put's it's magnitude to 1) so object moves at same speeds in all directions
r.AddForce (direction.normalized * speed); //Adds direction with magnitude of "speed" to rigidbody
}
Rigidbody MUST be attached to same GO as this script. This script uses world directions, because working with local directions is much harder (the object is rotating and changes directions rapidly, you can use it if you want just by replacing reference to Vector3 to transform like this:
if(Input.GetKey(KeyCode.W)) direction += transform.forward;
Of course for all direction.
This is very basic way to move the object along it's local axises, to do it more better you need to write specific scripts for specific sets of objects, it all depends what kind of object are you moving and how you want to move it. (is it sphere, cube..., will it ever fly up, should it rotate....).
If the RigidBody is Kinematic it is meant to be moved by means other than the physics system; animations, transform.position, etc. Make your rigid body non-kinematic and it should move when you set velocity.
I have a scene with a body maked with makehuman, and I need to add a simple prefab (a torus) around the arm of the body when the user touch the arm.
I tried:
Instantiate the prefab in the point where the user touch, but the prefab apear in the border of the arm.
Instantiate the prefab in the center of the arm, with this code:
float radio = hit.transform.collider.radius; // the arm has a capsuleCollider
Ray r = Camera.main.ScreenPointToRay(Input.GetTouch(0));
Vector3 origin = r.origin;
float distance = (origin - hit.point).magnitude;
RaycastHit ou;
Vector3 position = hit.point;
Ray r2 = new Ray(r.GetPoint(distance + 10f), -r.direction);
if (cc.Raycast(r2, out ou, distance + 10f))
position = (hit.point + ou.point) / 2;
Instantiate(Prefab, position, Quaternion.identity);
This try to Select the center of the arm and initialite a torus.
The second option works in some cases, but the general impression is that is the wrong way to do it.
How can I add a prefab around a collider? or, how can I modify the mesh to add a visual indicator?
This should work a lot better as well as look a lot cleaner:
Vector3 center = hit.transform.collider.bounds.center;
Instantiate(Prefab, center, Quaternion.identity);
hit.transform.collider is a vital part of this process and you got that part. collider.bounds is the bounding box that surrounds the collider (http://docs.unity3d.com/ScriptReference/Collider-bounds.html), and bounds.center is the center of the bounding box (http://docs.unity3d.com/ScriptReference/Bounds-center.html). The Vector3 that bounds.center returns is where you want to spawn your prefab.
From there, you should be able to rotate the prefab to the desired angle and perform any number of operations you want.
var startPoint =
shaft.transform.position
+ shaft.transform.forward;
var ray = new Ray(
startPoint,
-shaft.transform.forward
);
RaycastHit rayCastHit;
Physics.Raycast(ray, out rayCastHit);
var textured2D = (Texture2D)discoBall.renderer.material.mainTexture;
Vector2 textureCoord = rayCastHit.textureCoord;
Debug.Log(string.Format(
"{0},{1} at distance {2}",
textureCoord.x * textured2D.width,
textureCoord.y * textured2D.height,
rayCastHit.distance
));
I have a sphere with an object "Shaft" object inside it. I work out a startPoint as a distance away from the shaft in the direction the shaft points (to get outside the sphere). I then create a ray pointing back at the sphere with the same distance, so that it collides with the outside of my sphere.
The Debug.Log outputs x,y = 0,0 for the textureCoord, and the correct value of 0.35 for the distance. Why is the textureCoord always 0,0 when I do in fact have a material with a texture on my sphere?
Actually let me move my comment here, does the sphere use a mesh collider or a sphere collider? If it doesn't use a mesh collider, textureCoord returns Vector2.zero.
Update:
To change the collider type of a GameObject highlight it in the Unity editor and go to Component->Physics->MeshCollider. If prompted to 'Replace Existing Component', select 'Replace'.
GameObjects added from Unity's GameObject->Create_Other menu tend to default to colliders based on the shape of the object (spheres, boxes, etc), since mesh colliders are computationally more expensive.
Is the texture2d width and height actually what you expect? Possibly maintexture is not the correct texture on the shader you are using.