I have a character that drags a series of objects behind them, the character as a whole can grow as it eats, just imagine Snake in a somewhat more modern form. Each segment of the “Snake” is added to the body through a function that I call once enough things have been eaten. These segments, when generated are added to a list, which is then referenced to ensure that each segment is following the part it should be, including the base segment following the “head”, and that the “tail” follows the most recently created segment.
What I need to figure out, is how to detect all object that are encircled by the ‘Snake’ when the ‘head’ portion passes over the ‘tail’ portion
I’m working in CSharp.
Final Edit:
With the help and ideas of everybody, I finally got the results I was looking for using PolygonCollider2D:
public void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Tail")
{
//Use my List<T> of Snake segments to generate a List<T> of Vector2 using the position of each GameObject in the list
for(int i=0; i < segmentList.Count;i++)
{
Vector3 addVert;
addVert = segmentList*.gameObject.transform.position;*
addVert = new Vector2(addVert.x, addVert.y);*
surrounded.Add (addVert);*
}*
//Once new list is created, turn it into an array for use with PolygonCollider2D and Null out the list for next time.
Attach an enlarged collider according to your requirements on the red object and tag it
Check the minimum number( say “min” ) of symmetric objects required to surround the red object.
Attach colliders to the objects expected to surround the red object and select is trigger for each ( enable dynamically if objects are created during runtime).
Attach a script that uses a static variable counter ( say " surrounders ")on the objects that might surround the object.
When the objects at runtime gradually surround the object as soon as their trigger collision senses the tagged red object - increase the variable counter "surrounders"by 1 oncollisionenter. Oncollisionexit decrease the variable “surrounders” by 1.
On a script on red object when (surrounders >= min) … Then set state “SURROUNDED”…Then perform required function for surrounded object etc…
Given that you’ve changes the the definition to head crossing tail, then you can just walk the list of transforms. IsInside() takes a simple, closed path of transforms and a transform of a game object to test, and returns whether the position of the test object is inside the path.
function IsInside(path : Transform[], point : Transform) : boolean {
var v = path[1].position - path[0].position;
var left = IsLeft(v, point.position - path[0].position);
for (var i = 1; i < path.Length - 1; i++) {
v = path[i+1].position - path*.position;*
// One vector left of the other function IsLeft(v1 : Vector3, v2 : Vector3) : boolean { * var perp = Vector3.Cross(v1, v2);* * return Vector3.Dot(perp, Vector3.forward) >= 0.0;* } Note if you are going to be testing lots of objects, it might pay to pull the Transform[] into a Vector3[] array before cycling through all the objects. Also the IsLeft() function is the first thing I thought of, and for 2D I’m sure there are more efficient methods. Even Vector2.Angle() is likely faster for determining the relationship of two vectors.
Step 1: Give all segments of your snake a sphere trigger collider as well as the enemies that allows to use OnTriggerEnter to check for collisions. If your head or tail bumps into one of the elements you know you formed a circle.
Step 2: If a “circle” (it actually will be not a real circle but a polygon right? Any kind of 2D shape would be possible) is created gather all points of the segments that build the circle / polygon around it
Step 3 unity version: Create a PolygonCollider2D that is set to trigger to find collider in the region that is surrounded or use the PolygonCollider2D.OverlapPointmethod with every enemy to check if they are inside the polygon.
Step 3 efficient version: Use the points of the surrounding segments as vertex use your own implementation of OverlapPoint method to test if the enemies are inside. This would save you the allocation of the collider and a lot of internal physics calculation.
Step 4: If the tested position of the enemy is inside the polygon → job done.