Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
4
Question by Caiuse · Mar 14, 2011 at 12:08 PM · instantiatemeshprefab

Instantiate a Prefab along the surface of a Mesh

alt text

var prefab : GameObject;

function spawn() { var position = Random.onUnitSphere*2.5000; var spawnPreferences = Instantiate(prefab, position, Quaternion.identity); spawnPreferences.transform.eulerAngles.y = Random.Range(0, 360); }

I've managed to create a simple script to instantiate a prefab along the surface of a sphere, but i'm trying to use the same principle but create the instances along the surface of a mesh.

Any suggestions on how to do this. Sadly onUnitMesh doesn't exist!

Cheers - C

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AngryOldMan · Mar 14, 2011 at 12:20 PM 2
Share

again loving the diagram. Very helpful to explain what you want. I believe as a last resort you can put several spheres together to make the mesh on the left then restrict instantiation along the bits of each sphere. This is quite time consu$$anonymous$$g and fiddley as you need to make sure you have the random range set right for each seperate sphere so that you don't instantiate things inside the mesh. If you cant find an easier method this one atleast works with the script you already have (aslong as you configure the random.range)

avatar image Caiuse · Mar 14, 2011 at 12:24 PM 0
Share

Thanks @Bobadebob that sounds like a nice quick fix solution, which I'm going to use for now. Although I am looking for a solution for the long-run, planning of using a variety of different shaped meshes. Once again cheers.

2 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by Bunny83 · Mar 14, 2011 at 02:36 PM

The easiest way to get a random point on the surface of an irregular mesh in Unity would be to cast a random ray against the mesh. Every collider have a dedicated Raycast function to test only against this collider.

Both functions are not tested yet

function GetPointOnMesh() : RaycastHit{
    var length : float = 100.0;
    var direction : Vector3 = Random.onUnitSphere;
    var ray : Ray = Ray(transform.position + direction*length,-direction);
    var hit : RaycastHit;
    collider.Raycast (ray, hit, length*2);
    return hit;
}

The function returns a RaycastHit with all information on the point.

Another way would be to calculate a random triangle index and random barycentric coordinates and calculate the world position from this information.

function GetPointOnMesh() : RaycastHit{ var hit : RaycastHit; var mesh : Mesh = GetComponent.<MeshFilter>().mesh; hit.triangleIndex = Random.Range(0,mesh.triangles.Length/3); var BC : Vector3; BC.x = Random.Range(0.0,1.0); BC.y = Random.Range(0.0,1.0-BC.x); BC.z = Random.Range(0.0,1.0-BC.x-BC.y); hit.barycentricCoordinate = BC;

 var P1 : Vector3 = mesh.vertices[mesh.triangles[hit.triangleIndex + 0]];
 var P2 : Vector3 = mesh.vertices[mesh.triangles[hit.triangleIndex + 1]];
 var P3 : Vector3 = mesh.vertices[mesh.triangles[hit.triangleIndex + 2]];
 hit.point = transform.TransformPoint(P1*BC.x + P2*BC.y + P3*BC.z);

 // Interpolated vertex normal
 var N1 : Vector3 = mesh.normals[mesh.triangles[hit.triangleIndex + 0]];
 var N2 : Vector3 = mesh.normals[mesh.triangles[hit.triangleIndex + 1]];
 var N3 : Vector3 = mesh.normals[mesh.triangles[hit.triangleIndex + 2]];
 hit.normal = N1*BC.x + N2*BC.y + N3*BC.z;

 return hit;

}

If you need the face normal instead of the interpolated vertex normal you have to calculate it.

[...] var P1 : Vector3 = mesh.vertices[mesh.triangles[hit.triangleIndex + 0]]; var P2 : Vector3 = mesh.vertices[mesh.triangles[hit.triangleIndex + 1]]; var P3 : Vector3 = mesh.vertices[mesh.triangles[hit.triangleIndex + 2]]; hit.point = P1*BC.x + P2*BC.y + P3*BC.z;

 // Face normal
 hit.normal = Vector3.Cross((P1-P2),(P3-P2)).normalized;
 [...]

Both functions returns a RaycastHit structure. Keep in mind that the second method doesn't set all fields of hit.

If your mesh is more or less convex but with very different triangle sizes, the better point distribution you will get with the first function.
If the mesh have almost equal sized triangles but a very custom non convex shape the second would be better.

The first one is like a spherical projection onto the mesh. The second will covers all mesh triangles, even when they are hidden be other parts of the mesh.

To use this function do something like that:

var prefab : GameObject;

function spawn() { var randomPoint = GetPointOnMesh(); var spawnPreferences = Instantiate(prefab, randomPoint.point, Quaternion.identity); spawnPreferences.transform.eulerAngles.y = Random.Range(0, 360); }

You can use hit.normal with Quaternion.LookRotation to align the spawned object to the surface if you want but the axis that will point away from the surface have to be z in this case.

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Caiuse · Mar 14, 2011 at 05:19 PM 0
Share

Bunny83 thats an extremely informative answer, absolutely brilliant, I'm going to use the first method as I understand it better. Also the added information on using Quaternion.LookRotation is brilliant, I've been using a sperate LookAt script, not very practical. cheers +rep

avatar image Bunny83 · Mar 14, 2011 at 06:53 PM 0
Share

It's a very good and common question (way better than a lots of questions just asking for help on their own specific problems). I'm glad I could help. ;)

avatar image Argenex · Apr 29, 2011 at 01:50 AM 0
Share

" hit.triangleIndex = Random.Range(0,mesh.triangles.Length/3);" Returns: BCE0053: Property 'UnityEngine.RaycastHit.triangleIndex' is read only.

avatar image Bunny83 · Apr 29, 2011 at 02:08 AM 0
Share

Hmm, well, i've not checked the members of RaycastHit. I thought because it's a struct it's not a problem to setup your own RaycastHit but unfortunately the public members are all properties and some of them are read only. I'm not sure if they changed that recently or if they always have been properties. Anyways it's just a struct to return some information. If there's no way around that just use your own, custom struct/class. I don't see any good reason for a pure data holding structure to have readonly members...

avatar image Argenex · Apr 29, 2011 at 02:22 AM 0
Share

Yea thanks I found this to be a really good read as I am just simply instancing objects on a plane and restricting them to its surface. Thanks for the indepth answer!

Show more comments
avatar image
3

Answer by ScienceFiction · Jan 12, 2014 at 08:25 PM

You could also instantiate on the vertices of the mesh itself, picking from them randomly.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image kamyflex · Apr 11, 2020 at 06:15 PM 0
Share

Works fine in my case, Thanks.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Combining Meshes? 1 Answer

Changing game object based on variable state? 1 Answer

Find prefab from Instantiation 2 Answers

Reference a prefab to be instantiated in another scope 0 Answers

Attribute inheritance problem when using Instantiate 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges