- Home /
Getting a primitive mesh without creating a new GameObject
Hi folks,
I'm trying to make a single GameObject change it's mesh via C# script. For now, using the primitives as shapes will suffice. However, the function CreatePrimitive will always create a new GameObject, which I don't want.
Using C#, is there any way to get and assign a primitive's mesh without creating a new object?
Why are you trying to create the mesh at runtime? $$anonymous$$aybe you can approach this a different way?
In short, I run a socket server that accepts certain messages. These messages change the shape of the object, after which a screenshot is made and sent back.
I could create a new primitive, copy it's mesh and then delete it, but that seems needlessly complicated, especially since performance is very important. I want to change the mesh and screenshot it multiple times in quick succession.
Answer by DaveA · Aug 13, 2013 at 03:41 PM
If you need primitive meshes, I would just create a Mesh variable and assign it with the Inspector or in Start. You could just instantiate one of each primitive and then copy them to a new Mesh at Start. But really, just create a new Mesh at Start, and modify it as needed in Update (probably, or your on-network-request handler). Sample code here: http://docs.unity3d.com/Documentation/ScriptReference/Mesh.html If you are just changing shape, no point in destroying it each time, just adjust the x,y,z of the vertices as in example 2.
Answer by Octopoid · Dec 31, 2015 at 09:10 PM
I know this is old, but this thread was coming up first hit in Google for me. There are obviously a number of ways of sidestepping this, but I really just wanted a quick, reusable way of getting at the default primitive meshes. To this end I've put together a quick static helper class for this.
The first time you create a primitive of a given type without a MeshCollider or get a mesh of a given PrimitiveType there is an overhead of a GameObject being created and destroyed. All meshes are then cached into the class so if this is a performance concern you can simply call PrimitiveHelper.GetPrimitiveMesh(PrimitiveType.xxxxxx)
somewhere in your scene startup. Subsequent calls will then get the mesh out of the dictionary.
If you want to create a GameObject for a specific PrimitiveType without a MeshCollider you can call PrimitiveHelper.CreatePrimitive(PrimitiveType.xxxxxx, false)
PrimitiveHelper.cs
using System.Collections.Generic;
using UnityEngine;
public static class PrimitiveHelper
{
private static Dictionary<PrimitiveType, Mesh> primitiveMeshes = new Dictionary<PrimitiveType, Mesh>();
public static GameObject CreatePrimitive(PrimitiveType type, bool withCollider)
{
if (withCollider) { return GameObject.CreatePrimitive(type); }
GameObject gameObject = new GameObject(type.ToString());
MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
meshFilter.sharedMesh = PrimitiveHelper.GetPrimitiveMesh(type);
gameObject.AddComponent<MeshRenderer>();
return gameObject;
}
public static Mesh GetPrimitiveMesh(PrimitiveType type)
{
if (!PrimitiveHelper.primitiveMeshes.ContainsKey(type))
{
PrimitiveHelper.CreatePrimitiveMesh(type);
}
return PrimitiveHelper.primitiveMeshes[type];
}
private static Mesh CreatePrimitiveMesh(PrimitiveType type)
{
GameObject gameObject = GameObject.CreatePrimitive(type);
Mesh mesh = gameObject.GetComponent<MeshFilter>().sharedMesh;
GameObject.Destroy(gameObject);
PrimitiveHelper.primitiveMeshes[type] = mesh;
return mesh;
}
}
Obviously nothing special, but just thought I'd stick this up to save anyone else that comes across this a few minutes!
Awesome script, I'm adding this to my "Unity Helpers"-project! ^^
Answer by Glurth · Aug 09, 2017 at 06:43 PM
Check out Bunny83's answer to my question over here:http://answers.unity3d.com/questions/1377941/getassetpath-returning-incomplete-path-for-default.html
It provides some amazing (Editor-Only) methods to access built-in objects.
calling:
builtinCubeMesh=AssetDatabaseHelper.LoadAssetFromUniqueAssetPath< Mesh > ( "Library/unity default resources::Cube");
will load the built-in cube mesh (without the need to create and destroy GameObjects).
You can determine the "UniquePath" to use for ANY built-in object, including meshes, by passing it to the GetUniqueAssetPath function and noting the return value.
That's really interesting, I hadn't seen that double colon notation before.
It's worth noting this can't be used at runtime though, only in Editor scripts.
The double colon notation is specific to the AssetDatabaseHelper class by Bunny83, in that link I posted: It won't work with the regular unity load asset function. Editor Only: good point!
Doh, should have read it more carefully! I'm with you, it's getting everything of the right type out of the default resources, then returning by name match. Looks like a handy helper!
Answer by TobiasB · Dec 18, 2018 at 11:11 AM
Just a follow-up on this problem. I know this is an old question, but I have also been searching a lot on this problem. And I really don't understand why Unity doesn't make a lot easier to get the references to built-in primitive meshes. I was using the AssetDatabaseHelper class before but that stopped working after we switched to 2018.3. So here is a pretty clean implementation I made that works great in 2018.3. And it is caching the mesh refs as I need to be able to use them in GUI draw per frame:
public static Mesh GetUnityPrimitiveMesh(PrimitiveType primitiveType)
{
switch (primitiveType)
{
case PrimitiveType.Sphere:
return GetCachedPrimitiveMesh(ref _unitySphereMesh, primitiveType);
break;
case PrimitiveType.Capsule:
return GetCachedPrimitiveMesh(ref _unityCapsuleMesh, primitiveType);
break;
case PrimitiveType.Cylinder:
return GetCachedPrimitiveMesh(ref _unityCylinderMesh, primitiveType);
break;
case PrimitiveType.Cube:
return GetCachedPrimitiveMesh(ref _unityCubeMesh, primitiveType);
break;
case PrimitiveType.Plane:
return GetCachedPrimitiveMesh(ref _unityPlaneMesh, primitiveType);
break;
case PrimitiveType.Quad:
return GetCachedPrimitiveMesh(ref _unityQuadMesh, primitiveType);
break;
default:
throw new ArgumentOutOfRangeException(nameof(primitiveType), primitiveType, null);
}
}
private static Mesh GetCachedPrimitiveMesh(ref Mesh primMesh, PrimitiveType primitiveType)
{
if (primMesh == null)
{
Debug.Log("Getting Unity Primitive Mesh: " + primitiveType);
primMesh = Resources.GetBuiltinResource<Mesh>(GetPrimitiveMeshPath(primitiveType));
if (primMesh == null)
{
Debug.LogError("Couldn't load Unity Primitive Mesh: " + primitiveType);
}
}
return primMesh;
}
private static string GetPrimitiveMeshPath(PrimitiveType primitiveType)
{
switch (primitiveType)
{
case PrimitiveType.Sphere:
return "New-Sphere.fbx";
break;
case PrimitiveType.Capsule:
return "New-Capsule.fbx";
break;
case PrimitiveType.Cylinder:
return "New-Cylinder.fbx";
break;
case PrimitiveType.Cube:
return "Cube.fbx";
break;
case PrimitiveType.Plane:
return "New-Plane.fbx";
break;
case PrimitiveType.Quad:
return "Quad.fbx";
break;
default:
throw new ArgumentOutOfRangeException(nameof(primitiveType), primitiveType, null);
}
}
private static Mesh _unityCapsuleMesh = null;
private static Mesh _unityCubeMesh = null;
private static Mesh _unityCylinderMesh = null;
private static Mesh _unityPlaneMesh = null;
private static Mesh _unitySphereMesh = null;
private static Mesh _unityQuadMesh = null;
Answer by duadikos · Nov 26, 2018 at 05:01 AM
I also had this issue and couldn't instantiate a game object because it was triggering a collider, and it needed to work outside of the editor. I solved it in a very simple way:
Setup (one time):
1 - In the GUI, create a new sphere object.
2 - Delete all component except the primitive mesh
3 - Save it as a prefab to a Resources folder (e.g. "Assets/Resources/SphereMesh").
Usage:
Add the following code whenever you need to use a primitive mesh:
MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
meshFilter.mesh = Resources.Load<GameObject>("SphereMesh").GetComponent<MeshFilter>().sharedMesh;
where "gameObject" is the thing you want to add a primitive mesh to.
Your answer
Follow this Question
Related Questions
Load default quad mesh from resources 1 Answer
Resize single face of a primitive object like a cube 0 Answers
Trouble assigning vertices in a mesh to connect to other meshes vertices. 1 Answer
Return a single face from a cube primitive for manipulation 1 Answer
Is it possible for transparent spheres to look like they're intersecting? 1 Answer