Home>

We are making multi-jointed player characters such as worms of "MEGA WORM" and "DEATH WORM". It is a 2D game.

As shown in the figure above, I want to make several body objects connected in a series follow the trajectory of the head object at fixed intervals.
It doesn't work in the current way. I would like to know the improvements and other methods.

The problem is
[1: Cannot connect beads at fixed intervals]
The trajectory (transform.position) of the head object is saved in Vector<2>in List<>for about 10 frames, and the transform.position of the body object held in another List<>is updated every frame. ..
However, if the moving speed of the head object becomes faster, such as when falling, the distance between the head object and the body object will increase,
It looks like my neck is stretched.
How can I make a parabolic movement with the head object and each body object fixed, while keeping the beads connected?

[2: Movement of body object looks unnatural]
I am updating transform.position every frame, but it looks more like an afterimage than a body.
How can I make it move smoothly like the movement of the head object?

Applicable source code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BumperToBumper: MonoBehaviour
{

private Listpoints;// Record the position of the head object.
float appendDistance = 0.5f;// Fixed distance between each body and head.
private float appendSqrDistance;

int maxPointCount = 10;// Maximum number of miracle records.

public GameObject _body;// A prefab for body objects.
public GameObject Head;// Reference the head object.

List_bodyList = new List();// A list of body objects.

private int _bodyNum = 10;// The number of articulated joints. The number of body objects.

void Start()
{
setVectors();
}

void Awake()
{
appendSqrDistance = Mathf.Pow(appendDistance, 2);
Head = GameObject.Find("Head");

// Creating a body object.
//Managed by List.
for (int i = 0;i<_bodyNum;i++)
{
GameObject bodypref = Instantiate(_body) as GameObject;
_bodyList.Add(bodypref);
}
}

void OnValidate()
{
//appendDistance squared
appendSqrDistance = Mathf.Pow(appendDistance, 2);
}

void Update()
{
setPoints();
}

// Record the transform.position of the head object
void setPoints()
{

Vector2 curPoint = new Vector2(Head.transform.position.x, Head.transform.position.y);

if (points == null)
{
points = new List();
points.Add(curPoint);
}

// Add points.
addPoint(curPoint);

// Delete if the maximum number is exceeded.
while (points.Count>maxPointCount)
{
points.RemoveAt(0);

}

}

void addPoint(Vector2 curPoint)
{
//If the speed of movement of the head becomes faster, the neck seems to be stretched, so I'm going to take measures against that...
//The distance to the body object closest to the head is divided into fixed intervals...
//Why do you know why?
while (true)
{
var distance = (curPoint-points[points.Count-1]);
if (distance.sqrMagnitude

distance *= appendDistance/distance.magnitude;
points.Add(points[points.Count-1] + distance);
}

// Updating the position of each body object.
// My body looks like an afterimage and I get screen sick…
for (int i = 0;i<_bodyNum;i++)
{
_bodyList[i].transform.position = new Vector3(points[_bodyNum-1-i].x, points[_bodyNum-1-i].y);

}

}
}

The movement of the head object is controlled by another file.

If i am underground:
Move at a constant speed, change the direction of movement with the four-way controller

When jumping to the ground:
Performs an orthographic projection parabolic movement. Player input will not be accepted.

RigidBody2D and CircleCollider2D are attached to the head and body respectively, and Kinematic is turned on. Physical calculation is not used.

x = position.x of previous frame + initial velocity * Mathf.Cos(projection angle) * tick time;
y = position.y of previous frame + initial velocity * Mathf.Sin (projection angle) + (gravity * tick time * tick time) * 0.5f;

What I tried

I tried HingeJoint2D and DistanceJoint2D, but it didn't work.

If i have any questions, please feel free to contact us. Nice to meet you.

Supplementary information (FW/tool ​​version, etc.)

environment:
UNITY 2018.2.18f1 64bit
VisualStudio2017 for Unity

  • Answer # 1

    Since the history is the time, it will inevitably grow if it moves fast
    Since it seems to be a parabola, it is necessary to obtain accurate coordinates, but
    It's troublesome, so it's a method of linear interpolation to find coordinates like that.

    Vector2 DistancePoint(float distance){
        float work = distance;
        for (int i = 1;i<point.Length;i++){
            var p2en = (points[i-1]-point[i]).magunitude;
            if (0<pren&&work<plen){
                return Vector2.Lerp(points[i-1], point[i], work/plen);
            }
            work -= plen;
        }
        return point[point.Length-1];
    }

    -# I am not compiling, so if you get an error please fix it yourself