Unity 3D colision of objects - c#

I have a 3D game that is generated randomly when you hit play. The thing is that objects don't generate with collision and characters start moving through walls. What is the necessary code for an object to be generated with collision in C# ?

Ok if I have read your question correctly, you are auto generating random meshes for you game but they do not yet have colliders on them. To generate a collider for an object in c# see the following example:
using UnityEngine;
using System.Collections;
public class AddComponentExample : MonoBehaviour
{
void Start( )
{
SphereCollider sc = gameObject.AddComponent<SphereCollider> as SphereCollider;
}
}
You need to add a collider component to the gameobject you are generating. The one you choose depends on the mesh you created, so if you are generating cube meshes choose a box collider.
If you are creating your own meshes instead of primitives that are more complex then you can apply a "MeshCollider". But be warned if you are creating your own mesh at run time you may get some unusual artefacts.
Hope that helps

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

Giving a game object velocity/speed and converting vectors points

I'm currently developing a game in unity using c# scripts and I have a small problem. I'm trying to give one of my game objects a constant speed/velocity without it being affected by other gravity, drag or any other type of physics characteristic except velocity. I looked through the Unity manual to find any classes that would be able to help me with this and I seemed to have found one class that would do the job:
https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html
I edited it in order to make it fit my game since this is a game object that doesn't have its velocity affected by the player but every time I run the game in the test screen nothing happens(The object stays static). I was wondering if anyone knows of a class in Unity or C# that deals with this problem or generally knows how I can make this happen. Both by having it affect all the game objects appearing on the screen at the same time or only a select few? And secondly, I was also wondering how I could convert the rigidbody velocity vector2 into from a world point into a screen point?
Thanks alot.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallSpeed : MonoBehaviour
{
public Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
rb.velocity = new Vector2(0, 100);
}
}
Expected result: The game object moves upwards with a speed of 100.
Actual result: Nothing happens.
If you are trying to make your object move at a constant speed, there is no need for a rigidbody reference.
public float upSpeedPerSecond = 100f;
void Update() {
transform.translate(new Vector3(0, upSpeedPerSecond*time.deltaTime, 0));
}
Be sure to check that your Rigidbody2D is set to dynamic in the inspector, as Kinematic and Static rigidbodies do not have physics. If you don't want it to be dynamic, just use rb.Translate() instead. However, NEVER translate a static rigidbody, as it messes with the optimizations the engine does to them, use kinematic rigidbodies for transforming instead.

Enabling multiple Monobehaviour Components in a game object

So, i'm trying to make a Multiplayer Game here with various game objects and scripts in c# for every object on the scene.
Thing is, when i spawn the player controlled objects every player shares control over scripts for each spawned gameObject on the scene, that means, when somebody presses "s" for example, every player moves backwards, and that's not how i want game to behave.
--So, the only way i know to solve this, is by spawning 'em with all their scripts (the components) disabled and enable 'em with another script on the gameobject, but i had to make a script to enable every component one by one, and it got really time comsuning to create or edit a new script every time i add a new one to new units n' so on, so i figured out i could do something like this script below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class PlayerNetControl : NetworkBehaviour {
public MonoBehaviour[] components2enable;
public override void OnStartLocalPlayer()
{
foreach (MonoBehaviour cmp in components2enable)
{
cmp.enabled = true;
}
}
}
after doing this, i expected every "monobehaviour component" i added to the script using unity, to be enabled when for the player who controlled the game object only, but it does nothing, i check the components on the gameobject testing this out, they are all still disabled.
Also, is there any way for me to solve this problem in any other way than the one i know? if so, i would love you to illuminate me teaching me how.
Please help, i've started coding recently and i really need help with C#
Check for islocalplayer.
I think this solves all your problems.
https://docs.unity3d.com/ScriptReference/Networking.NetworkBehaviour-isLocalPlayer.html

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.)

OnCollisionEnter() not working in Unity3D

I have an object with a mesh collider and a prefab with sphere collider. I want the instance of the prefab to be destroyed if the two collide.
I wrote the following in a script:
private void OnCollisionEnter(Collision c)
{
if (c == target)
Destroy(transform.gameObject);
print("something"); // Doesn't get printed
}
But it is not working. I have tried toggling isTrigger on both the objects.
I had the same problem of OnCollisionEnter not being called and found this question.
For me, the problem was that I was making a 2D game so the answer is to use the OnCollisionEnter2D function instead.
Have a look at this table
If you want your OnCollisionEnter to be called make sure:
(a) Both objects have a collider attached.
(b) None of the objects is a trigger collider (this will issue OnTrigger function & not OnCollisionEnter)
(c) One of the objects (doesn't matter which of them) is a rigid, non kinematic & non static object (the second don't have to be a rigid body).
(d) Due to computational difficulties MeshCollider might have hard times colliding with other mesh collider, use them with caution.
(e) Make sure both the objects are in the same layer (or at least that they collide in scene settings).
(f) If you are working in 2d - OnCollisionEnter2D will be called, rename your function.
Make sure one of them has a non-kinematic rigidbody attached. Taken from the Unity docs:
When a collision between two Colliders occurs and if at least one of them has a Rigidbody attached, three collision messages are sent out to the objects attached to them. These events can be handled in scripting, and allow you to create unique behaviors with or without making use of the built-in NVIDIA PhysX engine.
From here: Unity3D MeshCollider
I had a similar problem. The box collider wasn't as big as the collision object. Setting the x and z values to 2 units fixed the problem!
Have you tried using the OnTriggerEnter() method and setting a collider on the object to a trigger?
If it doesn't need to tell what object its colliding with you could do a simple
void OnTriggerEnter(){
Destroy(transform.gameObject);
}
Edit:
Also I have done OnCollision like this
private string hitobject;
void OnCollisionEnter(UnityEngine.Collision hit)
{
hitobject = hit.gameObject.tag;
if(hitobject == "Plane")
{
isgrounded = true;
}
}
None of the objects are triggers and they don't need rigid bodies to work.

Categories

Resources