【发布时间】:2019-08-17 17:00:02
【问题描述】:
我问过这个question two years ago。一直没有成功,直到最近我才放弃了这个想法。
我已经能够半修复/复制机制。但是,所有对象似乎都跳到了下一个位置,其中一些重复了它们的“领导者”位置。
橙色是头部,身体部位是绿色。
从下面注释掉的代码中可以看出,我尝试了多种排列方式让孩子们顺利跟随他们的领导者,每个身体部位之间的距离只是圆对撞机的半径。
我的想法是,如果“leader”已经移动了半径的距离,那么follower可以向leader的旧位置移动。这让领导者有时间移动。
但唯一似乎半工作的,是未注释的。
谁能看出问题所在?
FollowTheLeader.cs
public class FollowTheLeader : MonoBehaviour
{
[Header("Head")]
public GameObject bodyPart;
public int bodyLength = 6;
[Header("Move Speed")]
[Range(0.25f, 2.0f)] public float moveMin = 0.5f;
[Range(0.25f, 2.0f)] public float moveMax = 2.0f;
[Header("Change Directions")]
[Range(0.25f, 2.0f)] public float changeMin = 0.5f;
[Range(0.25f, 2.0f)] public float changeMax = 2.0f;
[SerializeField]
private Vector2 oldPosition;
public Vector2 OldPosition { get => oldPosition; set => oldPosition = value; }
[SerializeField]
private Vector2 moveDirection = new Vector2(0, -1);
public Vector2 MoveDirection { get => moveDirection; set => moveDirection = value; }
[Header("Child")]
public int index;
public bool isChild;
public FollowTheLeader leader;
public float leaderDistance;
private CircleCollider2D m_collider2D;
private Rigidbody2D body2d;
private float moveSpeed;
private float moveTimePassed;
private float changeDirInterval;
private void Awake()
{
m_collider2D = GetComponent<CircleCollider2D>();
body2d = GetComponent<Rigidbody2D>();
AddBodyParts();
DefineDirection(moveDirection);
}
private void AddBodyParts()
{
if (isChild || bodyPart == null)
return;
//The head will generate its body parts. Each body part will have reference to the one before it.
FollowTheLeader temp = this;
for (int i = 1; i <= bodyLength; i++)
{
GameObject bp = Instantiate(bodyPart, transform);
bp.transform.SetParent(null);
//bp.transform.position = transform.position;
bp.transform.position = new Vector2(i * m_collider2D.radius, 0);
bp.name = $"Body {i}";
FollowTheLeader c = bp.AddComponent<FollowTheLeader>();
c.isChild = true;
c.index = i;
c.OldPosition = bp.transform.position;
c.leader = temp;
// cache the parent for the next body part
temp = c;
}
}
private void Start()
{
OnNewDirection();
}
private void FixedUpdate()
{
//Store the old postion for the next child
OldPosition = body2d.position;
// If child
if (isChild)
{
// Calculate the leaders distance
leaderDistance = Vector2.Distance(OldPosition, leader.OldPosition);
// We only want to move if the parent is as far away as the m_collider2D.radius.
if (leaderDistance < m_collider2D.radius)
return;
// BARELY ANY MOVEMENT
//body2d.MovePosition(leader.OldPosition.normalized);
//body2d.MovePosition(leader.OldPosition.normalized * moveSpeed);
//body2d.MovePosition(leader.OldPosition.normalized * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition.normalized * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition.normalized * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
//FLYS ALL OVER THE PLACE
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * moveSpeed);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * m_collider2D.radius * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
// BARELY ANY MOVEMENT
//body2d.MovePosition(leader.OldPosition * moveSpeed);
//body2d.MovePosition(leader.OldPosition * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
//FLYS ALL OVER THE PLACE
//body2d.MovePosition(body2d.position + leader.OldPosition);
//body2d.MovePosition(body2d.position + leader.OldPosition * moveSpeed);
//body2d.MovePosition(body2d.position + leader.OldPosition * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition * m_collider2D.radius * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
// KINDA FOLLOWS BUT ALL SEEM TO JUMP INTO THE SAME POSITION AS SEEN IN THE GIF
body2d.MovePosition(leader.OldPosition);
return;
}
// HEAD ONLY
// Countdown to next direction change
moveTimePassed += Time.deltaTime;
if (moveTimePassed >= changeDirInterval)
{
OnNewDirection();
}
// Calculate the next position
body2d.MovePosition(body2d.position + MoveDirection.normalized * moveSpeed * Time.deltaTime);
}
public void OnNewDirection()
{
moveTimePassed = 0;
moveSpeed = Random.Range(moveMin, moveMax);
changeDirInterval = Random.Range(changeMin, changeMax);
RandomDirection();
}
private void RandomDirection()
{
switch (Random.Range(0, 4))
{
case 0:
DefineDirection(Vector2.up);
break;
case 1:
DefineDirection(Vector2.right);
break;
case 2:
DefineDirection(Vector2.down);
break;
case 3:
DefineDirection(Vector2.left);
break;
default:
DefineDirection(Vector2.down);
break;
}
}
public void DefineDirection(Vector2 direction)
{
if (direction.Equals(Vector2.up))
{
MoveDirection = Vector2.up;
}
if (direction.Equals(Vector2.down))
{
MoveDirection = Vector2.down;
}
if (direction.Equals(Vector2.left))
{
MoveDirection = Vector2.left;
}
if (direction.Equals(Vector2.right))
{
MoveDirection = Vector2.right;
}
}
}
【问题讨论】:
-
您是否有理由要通过代码执行此操作?孩子们必须移动到确切的父母位置吗?你有没有看过
Joints(Unity one,不是你抽的那个)的用法? -
@Immorality 我想要一个特定的移动风格,而关节不给我那种风格。