Instantiate prefab around a object - unity3d

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.

Related

Unity rotation calculation

//RAYCAST
RaycastHit hit = new RaycastHit();
if(Physics.Raycast(impact.position, bloom, out hit, 1000f, canBeShot))
{
GameObject newBulletHole = Instantiate(bulletHolePrefab, hit.point + hit.normal * 0.001f, Quaternion.identity) as GameObject;
newBulletHole.transform.LookAt(hit.point + hit.normal);
Destroy(newBulletHole, 5f);
}
//Bullet
bulletSpawnPoint = GameObject.Find("BulletSpawn").transform;
var bullet = Instantiate(bulletPrefab, bulletSpawnPoint.position, **bulletSpawnPoint.rotation**);
bullet.GetComponent<Rigidbody>().velocity = bulletSpawnPoint.forward * loadout[currentIndex].bulletSpeed;
I need to get the perfect "bulletSpawnPoint.rotation" depending of my bullet hole created by the raycast hit. Thanks
enter image description here
So you want to spawn the bullet and then use Rigitbody to move it to the newBulletHole gameobject.
Easy way would be to store position of the bullet hole and then pass it into LookAt method of the bullet Transform before adding velocity.
A bit more advanced way (and this is what you are asking in your question, afaik): calculate the direction vector (bulletSpawnPoint.transform.position - newBulletHole.transform.position) and then get Quaternion (i.e. rotation) with LookRotation

how to limit drag and drop to parent object

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);
}

check if centerPlane is not near edge in unity

I'm trying to make whack a mole game using project tango.
When user start the game, the program will create holes at random point for the moles to come out. Right now, I already can make the hole and spawn the mole at random, though I have a problem with the created hole.
The hole sometimes spawn at an edge contour of table and stuff and make the hole partially floating in the air. Is there any way to check if the centerPlane is near an edge or not?
Here's the screenshot of the problem I meant. I want the "hole" not to spawn on area that doesn't fit with it's height and width. Currently, I'm using farandole release.
EDIT 1:
I'm trying to do as Hristo suggest. But it doesn't work, the FindClosestPoint always return -1, even when I use the center of the screen. Here's the script I used. And for some additional info, I'm using the unitySDK and unity 5.5.2f1
bool CheckTheCorner(Camera cam,Vector3 planeCenter){
Vector2 firstPointInScreen = WorldToScreenConverter(cam,new Vector3 (planeCenter.x,planeCenter.y,planeCenter.z-holeheight));
Vector2 secondPointInScreen = WorldToScreenConverter(cam,new Vector3 (planeCenter.x,planeCenter.y,planeCenter.z+holeheight));
Vector2 thirdPointInScreen = WorldToScreenConverter(cam,new Vector3 (planeCenter.x-holewidth,planeCenter.y,planeCenter.z));
Vector2 fourthPointInScreen = WorldToScreenConverter(cam,new Vector3 (planeCenter.x+holewidth,planeCenter.y,planeCenter.z));
DebugText.text = m_pointCloud.FindClosestPoint (cam, new Vector2(Screen.width / 2, Screen.height / 2), 1).ToString ();
Vector3 firstPoint = m_pointCloud.m_points[m_pointCloud.FindClosestPoint(cam, firstPointInScreen, 1)];
Vector3 secondPoint = m_pointCloud.m_points[m_pointCloud.FindClosestPoint(cam, secondPointInScreen, 1)];
Vector3 thirdPoint = m_pointCloud.m_points[m_pointCloud.FindClosestPoint(cam, thirdPointInScreen, 1)];
Vector3 fourthPoint = m_pointCloud.m_points[m_pointCloud.FindClosestPoint(cam, fourthPointInScreen, 1)];
return false;
}
Vector2 WorldToScreenConverter(Camera cam,Vector3 worldPos){
Vector3 screenPos = cam.WorldToScreenPoint (worldPos);
return new Vector2 (screenPos.x,screenPos.z);
}
Ah yes, don't mind the return false one for the moment, I just put it there to avoid error since I'm still figuring out the FindClosestPoint.
What you can do is take the 4 corners on your plane and decide if they are all laying on a surface in the real world, if not you can make the plane elsewhere.
That can happen with the use of FindClosestPoint() method in the TangoPointCloud.cs. What that method does is makes a Raycast from your camera trough a certain point on the screen landing in the real world environment. The method then returns the index of that point. The list to search with the indexes is called m_points
So lets split it in steps:
Make 4 Vectors using the `FindClosestPoint().
Check if all 4 vectors are on the same plane (simple math).
If step 2 is true -> Instantiate your GameObject on that plane.
To get one of the vectors your code should be something like this:
Vector3 firstPoint = m_pointCloud.m_points[m_pointCloud.FindClosestPoint(Camera.main, new Vector2(Screen.width / 2, Screen.height / 2), 1)];
In this example I'm using the center of the screen as my Vector2 parameter. However you don't want the center of the screen . Instead you want the position of one corner from your plane translated as a screen point.
Hope that solves your problem. Cheers.

Move 3d object to mouse click position in unity

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

Why is Unity3D RaycastHit.textureCoord always 0,0?

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.