Create a single MeshCollider for mesh with many vertices - c#

I am doing some calculation with meshes in unity and adding MeshCollider's to calculate pathfinding. Some meshes that are generated are very big and splits meshes into 2 or more 'mesh parts'. I set MeshCollider like so:
testRoom = GameObject.Find("testroom");
MeshFilter[] _filters = testRoom.GetComponentsInChildren<MeshFilter>();
foreach (MeshFilter _filter in _filters)
{
_verts.AddRange(_filter.mesh.vertices);
_triangles.AddRange(_filter.mesh.triangles);
testRoom.AddComponent<MeshCollider>();
testRoom.GetComponent<MeshCollider>().sharedMesh = _filter.mesh;
}
This obviously dont work with several meshparts since the Collider gets overwritten. Since the mesh is to big I cannot merge the meshes together and set a collider, right? When I use the Generate Colliders box in unity it works fine but I want a programmable solution since I am to generate the meshes at runtime.
Does anyone know how to make a single collider for the big mesh that is split into several parts due to having to many vertices?
Here is a picture of the mesh (as requested) It might look abit strange but it's (part of) an office building. I made the mesh myself using a Tango tablet. I diddnt include a tango tag because I did not think how the mesh looked would affect the answer.

I dont fully understand your situation, to be honest, but if you need a collider that will cover complex object created from script you still can add it to each object separately at runtime, right? So instead of
testRoom.AddComponent<MeshCollider>();
testRoom.GetComponent<MeshCollider>().sharedMesh = _filter.mesh;
you can do
var collider = _filter.gameObject.AddComponent<MeshCollider>();
collider.sharedMesh = _filter.mesh;
You cant add more than one MeshFilter component to a gameObject anyway, so any filter you get from testRoom.GetComponentsInChildren() is attached to a different object. Therefore you can add new collider to each one of them individually.

You can of course add the colliders at runtime as you are already doing. This will give you very heavy and poor performance solution that will work but slow. Normal practice in this case would be modelling lowpoly version of that mesh you will use as a collider.
Another solution if your objects aren't too complex would be box colliders. You would need to grab renderer.bounds
http://docs.unity3d.com/ScriptReference/Renderer-bounds.html
and create new box collider with that bounds
http://docs.unity3d.com/ScriptReference/Collider-bounds.html
Hope that make sense

Related

unity3d: How to save part of a prefab instance as a prefab?

I have a large room with tends of thousands of nested objects. I tried to select a group of objects that represents a single object out of hundreds. This was originally a sketchup file that got turned into a prefab variant and added to the scene.
using UnityEngine;
using System.Collections;
using UnityEditor;
public class CreatePrefab : MonoBehaviour
{
[MenuItem("Extras/Create Prefab From Selection")]
static void DoCreatePrefab()
{
Transform[] transforms = Selection.transforms;
foreach (Transform t in transforms)
{
GameObject prefab = PrefabUtility.CreatePrefab("Assets/Prefabs/" + t.gameObject.name +
".prefab", t.gameObject, ReplacePrefabOptions.ReplaceNameBased);
}
}
}
So I am trying to iterate through the selection and turn them each into prefabs. Its pretty ridiculous because there is close to 100,000 objects in total and everything, like nuts, bolts, rods that make up a chair are individual gameobjects.
I am trying to use GPU instancing to reduce framerate but this imported model needs to be converted into prefab somehow. I am trying to extract meaningful objects that repeat (ex. chairs) as individual chair prefabs but the problem is:
I don't know how to first combine/fuse the objects that make up a chair
If I am able to select a chair I need to be able to convert it into a chair prefab.
I have to basically repeat this process for each object that repeats excessively (ex. chairs, desks)
I get this error message from unity: can't save part of a prefab instance as a prefab,
How can I group the individual parts that make up a chair and turn it into a prefab?
Unity can neither handle that many objects nor a hierarchy this deep! (a nice article on Unity's own website about this). Thus you will never end up with good performance this way. You'll have to reduce and combine the objects in a dedicated software (usually 3D modeling software) and import those objects to unity.
The same requirement as your. Unity hasn't provided such a method to save a nested prefab modification, but can be achieved by a trick.
The solutions is:
Instantiate another nested prefab by PrefabUtility.InstantiatePrefab
Modify that new GameObject of the prefab
Save the modification by PrefabUtility.SaveAsPrefabAssetAndConnect
And because the gameobject hierarchy is a reference, the saved modification will also affect the nested prefab.
Here is the code:
var prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(goInScene);
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
var anotherGo = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
// Do the same modification of the nestedGo to anotherGo
PrefabUtility.SaveAsPrefabAssetAndConnect(anotherGo, prefabPath, InteractionMode.AutomatedAction); // This save will affect all prefab in Scene!
DestroyImmediate(anotherGo);

How can I grab a reference of a game-object in a scene from a prefab

currently I am working on a Equipment system that will Instantiate Game objects into the scene from a list, prior to this I was not using a Instantiation system with just keeping the Game Objects Active in the scene at all time.
Now with Instantiating the Game Object(Prefab) I am running into the error of Loosing the References when I instantiate them, I have looked at various other articles before such as this Discussion here:
However I am looking at alternative ways other than using Tags as this system may use a large amount of tags decreasing game performance overtime, would anyone know different methods as to saving references from a scene into a prefab?
So as this is a new system I am really just looking for suggestions on how to save references of scene game-objects into a prefab, as my old system was just holding the game objects active in the scene and not actually instantiating them, once again I would love to hear different types of methods, something more than just using Tags.
The References im trying to save are three Transform Elements from a script attached to my Prefab they are the following
public Transform camPos;
public Transform aimLocation;
public Transform crosshairLocation;
Currently I am just dragging and dropping the gameobjects from the scene into the public fields in the script
Since this will be a major system I would like to not want to use tags for this system. But it is definitely a Valid option I am just looking for other methods for saving references of scene game-objects into a prefab When Instantiating the prefab into the scene,
Thank you for taking the time to read and any suggestions would be greatly Appreciated!
Any Questions Just Ask!
You can not save scene references in prefabs, for obvious reasons (what happens if you instantiate that prefab into another scene?). Your prefab needs to discover the objects it needs after it's instantiated. I'm not a huge fan of the tag system in Unity (or any other system that uses strings as identifiers, too much room for error). I'd recommend you take any of these three approaches:
Make the transforms you need (cam pos, aim location, etc.) singletons if there's ever only going to be one of each. You'd make a script class specifically for each one, make that class a singleton, and put it on the game objects. Then, after your prefab is instantiated, you can do something like this: camPos = CamPos.Instance.transform; You can read up on the singleton pattern here.
If there's going to be more than one of each, group all related objects into a single hierarchy (that is, make them all the child of a single game object). For example, if there are going to be many characters and each is going to have a separate aim location, you can make aim location a child of the character game object. Then, in your prefab (take care to make the prefab a child of the same root game object as well), you can do something along these lines: camPos = transform.root.GetComponentInChildren<CamPos>().transform; Better yet, you can have a component that has references to all such objects, and attach one to the root game object. Then, you can do: camPos = transform.root.GetComponent<ReferenceRepository>().CamPos;
Initialize the prefabs when they're instantiated. For example, say you have a player class that instantiates a weapon and already has a reference to the camPos. You can do it like this: var weapon = Instantiate<Weapon>(myWeaponPrefab); weapon.CamPos = camPos; Note however that when you assign public fields this way, they will only be accessible once Start is called. In other words, they won't be available in Awake.
That said, I don't think making stuff like aim location and crosshair location separate objects is a very good idea anyway. You should have a player/human/pawn class, and that class can provide this information to other objects that need it.

Unity3d maintaining a minimum distance between multiple GameObjects c#

I have multiple enemies that move toward the player. I am trying to stop them from merging into each other, i.e maintain some type of minimum distance between each other. What I'm trying is this (from unity3d forums):
enemy1.transform.position = (enemy1.transform.position -
enemy2.transform.position).normalized * distance + enemy2.transform.position;
However, when I have >= 3 enemies they still seem to bunch up even when I apply this to every enemy combination.
I need a better method as this one does not work and does not scale.
What you do around your enemy prefab is place a quad box which in effect is a trigger element, then on you script for the enemy you set that if another enemy (using tag types, I imagine) comes within touching of the quad box then to run appropriate code to stop the enemy getting closer in and to prevent the enemy actually overlapping with this trigger box.
Your code you example in your question looks like it is referencing the enemy units specifically rather than as instance entitites which is very probably a bad way of coding, as you're finding, it's very inflexible dealing with not-specifically-named reference entities.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
private Transform otherEntity;
public float distance = 50.0f;
private Transform thisEntity;
void OnTriggerEnter(Collider other)
{
otherEntity = other.GetComponent<Transform>();
thisEntity = GetComponent<Transform>();
thisEntity.position = (thisEntity.position - otherEntity.position).normalized * distance + otherEntity.position;
}
}
I have not tested the above code but using the code you reference the values for the transform are loaded from the Game Component for the referenced entities, as this has changed ALOT in Unity since release of version 5.1 and your source for your code was an answer given in 2012!!
thisEntity is the object that the script is attached to, typically one of the enemy. The otherEntity is the object that comes within the quad trigger (please remember the quad needs to be referenced as a trigger element.
The values of the Entity variables need to be set once the trigger is entered, so that it always effects the correct other element.
(I may be totally wrong with my methodology but I hope this helps.)

Collisions between CharacterController and BoxCollider

I'm trying to detect collision between the characterController and a platform (a rigidBody + boxCollider) in an Unity project.
I know that I can use this function at the characterController object:
void OnControllerColliderHit(ControllerColliderHit hit) {
// [...];
}
But I would strongly rather to detect it in the platform object, in order to try to maintain the code clearer. Something like this:
void OnCollisionEnter(Collision c) {
Debug.Log(c.gameObject.tag);
}
But it is not working! I searched in Unity forums and apparently the only way to detect a collision is to set the boxCollider's property isTrigger as True and using .OnTriggerEnter(Collider c) method instead. However, doing it will cause the player to fall through the platform, which obviously can't happen.
Alright, so my question is: is there another way to do it - whithout setting isTrigger as True - and detecting the collision in the platform object?
Thank you!
The way I handled a similar problem with a platform and a character controller, is by adding a child object to the platform with a trigger collider set to a larger size than the platform itself (think of it like an invisible box surrounding your platform). What this does is allow you to know if your player is going to hit the platform, the direction he's coming from etc. Then it's a simple matter of sending a message to the platform, with an necessary information parentPlatformObject.SendMessage(params)
I would like to suggest something very similar to what Steven Mills suggested, but may make things easier in the long run.
Add a child object to the player, that has a trigger collision box the size of the player (or just around it's feet if that's what you care about), but has a specific layer only for itself. In the project physics settings, make said layer only interact with the platform's layer. This means you won't trigger if this box hits anything else except for the platforms (like the rest of the player). Since the non triggers had not changed, the player and the platform will behave as you expect (just as with Steven's solution) but if you add new types of objects that you wish to land on/hit, and want them to work in a similar manner, you will not need double the prefabs/make 2 objects, just 1 with the correct layer assigned.

C# XNA Farseer - Creating Shapes From Textures

I want to create collision vertices to attach to bodies in XNA with Farseer, according to loaded Texture2Ds.
A caveat, first of all. is that I'm not using Farseer for anything other than collision. Rendering and all other game code is done using my own engine. Farseer is just used as a background physics simulator (and will only tell me when a collision happens, and then I'll handle that myself).
I should point out here that I'm 100% new to Farseer. Never used it before.
So, if I create my List using BayazitDecomposer.ConvexPartition(verts), should I then store this data alongside the Texture2D objects; and then create List objects on the fly when I create my collidable actors? Or am I doing something wrong?
Furthermore, in the example at http://farseerphysics.codeplex.com/documentation, it scales the vertices by Vertices.Scale()... If I keep all my Farseer bodies in pixel space, do I need to do this?
Thank you.
So, if I create my List using BayazitDecomposer.ConvexPartition(verts), should I then store this data alongside the Texture2D objects; and then create List objects on the fly when I create my collidable actors? Or am I doing something wrong?
You create an instance of the Body class from a list of verts using the BodyFactory. I would suggest doing this for each actor you have. However, you can save yourself some processor power by reusing bodies. So if an actor dies add the body to a queue and then snap it to a new actor that is created.
Furthermore, in the example at http://farseerphysics.codeplex.com/documentation, it scales the vertices by Vertices.Scale()... If I keep all my Farseer bodies in pixel space, do I need to do this?
Nope. However that means that a pixel is a meter as far as Farseer is concerned. I believe the formula for Torque if Radius * Force so anything reliant on a radius wouldn't behave as expected. I suggest making the metes equivalent to what actually is a meter in the game. Its just a bit of extra division.

Categories

Resources