Get Mesh of particle collider - unity3d

How would I go about getting the mesh filter of a particle collision and than assign that mesh to the particle.
So I have a OnParticleCollision. I hit the object take this object I get its Mesh Filter. I than want to assign this to that of my particle so it takes the effect of its physical build.
Here is my code so far.
void Start()
{
Debug.Log("Script Starting...");
part = GetComponent<ParticleSystem>();
collisionEvents = new List<ParticleCollisionEvent>();
}
void OnParticleCollision(GameObject coll)
{
// Getting the object of the collider
Collider obj = coll.GetComponent<Collider>();
Mesh mesh = obj.GetComponent<MeshFilter>().mesh;
// Assign the mesh shape of the collider to that of the particle
ElectricWave.shape.meshRenderer = mesh; // I know this doesnt work as is.
// Play effect
ElectricWave.Play();
}

If you're wanting all particles in the system to take on that mesh, it's straightforward. Just get the collided-with object mesh and apply that to the ParticleSystemRenderer:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ParticleCollision : MonoBehaviour
{
private ParticleSystemRenderer particleRenderer;
void Start()
{
particleRenderer = GetComponent<ParticleSystemRenderer>();
}
void OnParticleCollision(GameObject other)
{
particleRenderer.renderMode = ParticleSystemRenderMode.Mesh;
particleRenderer.material = other.GetComponent<Renderer>().material;
}
}
However, if you instead are looking to change the mesh of only that particle, it will be a lot more complicated, since the ParticleCollisionEvent data does not contain which particle collided with it. A good starting point might be looking at the ParticleCollisionEvent.intersection value, and trying to find the particle nearest that point using GetParticles. It might be extrememly computationally expensive, though, if it works at all.
An easier way might be to fake it by having multiple particle systems with extremely low emission rates, so that changing the mesh of a whole particle system results in changing just one visible particle, and resetting the system's mesh before every new particle is emitted. That way you get the visual effect you're looking for, but under the hood it's multiple particle systems acting as one.

Related

Collision Layer Matrix and Parent/Child object relationships

I come here after some testing, and because after some googling, I was incapable of finding a straight answer.
Suppose I have a player character with a tag set to Player and a layer set to Humanoid. I also have a bunch of NPC performing patrol, wander, and other movement behaviors. Their tags are set to NPC and their layers to Humanoid. Since this is a 2D game using 2D physics, I used the Project Settings collision matrix to make it so that Humanoids do not collide with each other.
In other words, the NPCs and the player characters can pass through each other, while respecting gravity, force, impulse, etc... This is working fine. My problem arises when: I want some child GameObject of NPC which is in layer Default and has a CircleCollider2D of type Trigger and I want to detect that collision in order to perform some actions (e.g.: show dialogue, stop or switch AI Behaviour of the parent object, or others).
From my testing, this seems not to be working, but I might be doing something wrong. So my question is:
If a GameObject A ignores collisions against layer X, will collisions against a GameObject C in layer Y be ignored if C is a child of a GameObject P in layer X?
private void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.CompareTag("Player")) {
Debug.Log("Collided with player");
}
if (!eventConsumed && other.gameObject.CompareTag("Player")) {
var draw = Random.Range(0.001f, 1.0f);
if (draw > 1.0f - eventChance) {
dialogueEvent.Play();
dialogueEvent = null;
}
eventChance = Mathf.Clamp(eventChance * 1.33f, 0.0f, 1.0f);
}
}
In order to detect whether or not a physics collider that is set as a trigger has collided. You would need to use the OnTriggerEnter2D function instead of the OnCollisionEnter2D function.

How to detect a potential collision in Unity?

I have a Unity game I am working on as a hobby and have come across an interesting issue with how to best handle collision detection. My problem here is that my game is a 2D turn-based game, whereby a game object can move a fixed distance each time in a non-grid based world space. I have my game objects currently using BoxCollider2D to handle collision detection, but I need to be able to determine if there will be a collision BEFORE actually making a move, which right now causes the game object to overlap another game object and fire the OnCollisionEnter2D event. The eventual idea here is to allow a player to plan out a move and have a "navigation guide" appear next to the object to show move options based on the game object's move capabilities.
Is it possible to take my game object's collider, transform its position to move or rotate it, see if a collision would occur, but NOT actually move the object itself?
You mean like simply using Rigidbody.SweepTest ? ;)
Tests if a rigidbody would collide with anything, if it was moved through the Scene.
From the example
public class ExampleClass : MonoBehaviour
{
public float collisionCheckDistance;
public bool aboutToCollide;
public float distanceToCollision;
public Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
RaycastHit hit;
if (rb.SweepTest(transform.forward, out hit, collisionCheckDistance))
{
aboutToCollide = true;
distanceToCollision = hit.distance;
}
}
}
Oh just noted that actually this is only for 3D Rigidbody.
For 2D this doesn't exist but can be kind of replicated using instead Collider2D.Cast
Casts the Collider shape into the Scene starting at the Collider position ignoring the Collider itself.

Multiple Colliders on Complex Object

I have designed a complex city with thousand of objects like roads, sideways, buidlings, trees, etc. and imported to Unity3d
I want to put colliders over them, so that when player hit them, it should face collision and should not passes though them
Though it has many objects, if i put one by one collider to each object, it will take so much time. Is there any other way i can just select all of them and put collider.
Also, if i select all object and put colliders (Mesh Collider). it is not adding to the object
Please help
Editor Scripting to the rescue. I would write a tool similar to this example. It uses a Menu Item which can be selected via Window -> Collider Tool. It then runs our custom method to find all meshes, which we want to add a collider to, then adds one and also logs which GameObjects were changed.
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
public static class ColliderTool
{
[MenuItem("Window/Collider Tool")]
public static void RunTool()
{
List<MeshFilter> meshes = findObjectsThatNeedColliders();
for (int i = 0; i < meshes.Count; i++)
{
GameObject go = meshes[i].gameObject;
// Add a collider to each mesh and record the undo step.
MeshCollider collider = Undo.AddComponent<MeshCollider>(go);
// Use the existing mesh as the collider mesh.
collider.sharedMesh = meshes[i].sharedMesh;
Debug.Log("Added a new collider on: " + go.name, go);
}
Debug.Log("Done");
}
private static List<MeshFilter> findObjectsThatNeedColliders()
{
// This list will be filled with all meshes, which require a collider.
List<MeshFilter> meshesWithoutCollider = new List<MeshFilter>();
// Get all meshes in the scene. This only returns active ones.
// Maybe we also need inactive ones, which we can get via GetRootGameObjects and GetComponent.
MeshFilter[] allMeshes = GameObject.FindObjectsOfType<MeshFilter>();
foreach(MeshFilter mesh in allMeshes)
{
if(mesh.GetComponent<Collider>() == null)
meshesWithoutCollider.Add(mesh);
}
return meshesWithoutCollider;
}
}
You might need more complex rules about which objects require a collider and which type it should be, but a simple tool can still save you a lot of time before hand tweaking everything.
You should also consider making this selection based. The Selection class can give you a list of all selected objects. Some ideas:
Add a MeshCollider to all selected objects, if one doesn't already exist.
Add a BoxCollider to selected objects and scale it to an approximate size depending on the transform size or bounding box of the MeshRenderer.
My solution is based on your question about how to add a collider to many objects in a large scene. However, this might not be the overall best solution. Maybe too many MeshColliders hurt physics performance. You will most likely want to approximate most of the colliders with boxes and spheres, but of course you can still write a tool to help you with that.

Unity - Tricky Particle Collisions

I am making a prototype for my 2D game. It consists of a ball that launches missiles that are aimed to explode where the user clicks. The explosion of the missile releases particles, which hit the ball and exert a force on the ball. Here is a video.
I used a standard particle system with the Collision module activated. Then attached this script to the particle systems created be each explosion:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class particleInteraction : MonoBehaviour {
//PS Variables
ParticleSystem myPS;
public List<ParticleCollisionEvent> particleCollisions = new List<ParticleCollisionEvent>();
//Physics variables
public float effect;
// Use this for initialization
void Start () {
myPS = GetComponent<ParticleSystem>();
}
void OnParticleCollision (GameObject other)
{
//Checking if the hit object is indeed the ball
if (other.tag.Equals("Player"))
{
Rigidbody2D hitObject = other.GetComponent<Rigidbody2D>();
//Getting the number of particles hat hit the ball
int noOfCollisions = myPS.GetCollisionEvents(other, particleCollisions);
Vector3 particleDirection = new Vector2(0,0); //The overall velocity of all the particles that collided
//Iterating through all the collisions and adding their vectors
for (int i = 0; i < noOfCollisions; i++)
{
particleDirection += particleCollisions[i].velocity;
}
//Applying the resultant force
hitObject.AddForce(particleDirection.normalized * effect * noOfCollisions);
}
}
}
This mostly works, however it causes a problem. The missile are designed to explode when they hit the walls too, so when the ball is on a wall I expect a missile aimed at the wall to push the ball off of it. However, the ball simply jerks away from the wall in the next frame (can be seen in the video). I believe this is because of the colliders on the particles instantiating inside of the ball's collider. This causes the physics engine to immediately move the ball away in the next scene.
So I tried using OnParticleTrigger, however I realized that Unity doesn't provide info on the gameobject affected in particle triggers, so I cannot affect the ball.
Could anyone help me find a way to make this work? I want to avoid the jerky movement caused by the intersecting colliders, or maybe use a better method expressing the missile explosions.
reduce the Radius Scale under the Collision Tab.
you can visually debug this using visualize Bounds checked inside the module.

Unity - Inconsistant speed of object following raycast2D

So im creating a simple game and one component of the game is a greendot following the outside of the level. I got this working using a raycast in the middle which rotates and gives the position of collision the the gameobject.
game overview
The problem is that the speed is inconsistant at the moment since the distance between two collisions can be further distance if i have a slope. I also have the feeling that there should be a easier way to get the same result. What are your thoughts?
public class FollowPath : MonoBehaviour {
Vector3 collisionPos;
public GameObject greenDot;
void Update ()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.up);
transform.Rotate(0.0f, 0.0f, 3);
if (hit.collider != null)
{
collisionPos = hit.point;
}
greenDot.transform.position = collisionPos;
}
}
I'm not sure if you will like this answer, as it suggests a complete departure from the way you were trying to do it.
A simple way to do this, would be to give your moving dot GameObject a Rigidbody2D component, AND a CircleCollider component.
Then, make your walls, and add to each an EdgeCollider component.
You'll probably also want to add a PhysicsMaterial2d to each GameObject with a Collider and set the friction and bounciness values for each.
Once this is setup, you can apply an initial force to the rigid body ball to get it moving, and it will bounce off the walls just like a ball does, using the Unity physics engine. No code would be needed in you update functions.