- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我问这个question two years ago .一直没有成功,直到最近我才放弃这个想法。
从那以后,我已经能够半修复/复制该机制。然而,所有的物体似乎都跳到了它们的下一个位置,有些物体重复了它们“领导者”的位置。
橙色是头部, body 部位是绿色。
正如您从下面注释掉的代码中看到的那样,我尝试了多种排列方式让 children 顺畅跟随他们的领导者每个 body 部位之间的距离只是圆形碰撞器的半径。
我的想法是,如果“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;
}
}
}
最佳答案
您可以通过许多不同的方式来处理它,但让我向您展示一种方式。
Snake
- 使领导者向前移动,在路径中创建新点,管理小兵Path
- 包含所有点的环形缓冲区Minion
- 根据与领导者的距离遵循路径这是一个显示小发明的例子:
蛇是主要逻辑所在的地方。
蛇自动向前移动。当领导者和最后一个点之间的距离大于 RADIUS
时,我们创建一个新点。然后,我们沿着点的路径移动所有小兵。
public class Snake : MonoBehaviour
{
public const float RADIUS = 1f; // distance between minions
public const float MOVE_SPEED = 1f; // movement speed
public Vector2 dir = Vector2.up; // movement direction
public float headDist = 0f; // distance from path 'head' to leader (used for lerp-ing between points)
public Path path = new Path(1); // path points
public List<Minion> minions = new List<Minion>(); // all minions
public Minion Leader => minions[0];
void Awake()
{
path.Add(this.transform.position);
AddMinion(new Knight());
}
void AddMinion(Minion minion)
{
// Initialize a minion and give it an index (0,1,2) which is used as offset later on
minion.Init(minions.Count);
minions.Add(minion);
minion.MoveOnPath(path, 0f);
// Resize the capacity of the path if there are more minions in the snake than the path
if (path.Capacity <= minions.Count) path.Resize();
}
void FixedUpdate()
{
MoveLeader();
MoveMinions();
}
void MoveLeader()
{
// Move the first minion (leader) towards the 'dir'
Leader.transform.position += ((Vector3)dir) * MOVE_SPEED * Time.deltaTime;
// Measure the distance between the leader and the 'head' of that path
Vector2 headToLeader = ((Vector2)Leader.transform.position) - path.Head().pos;
// Cache the precise distance so we can reuse it when we offset each minion
headDist = headToLeader.magnitude;
// When the distance between the leader and the 'head' of the path hits the threshold, spawn a new point in the path
if (headDist >= RADIUS)
{
// In case leader overshot, let's make sure all points are spaced exactly with 'RADIUS'
float leaderOvershoot = headDist - RADIUS;
Vector2 pushDir = headToLeader.normalized * leaderOvershoot;
path.Add(((Vector2)Leader.transform.position) - pushDir);
// Update head distance as there is a new point we have to measure from now
headDist = (((Vector2)Leader.transform.position) - path.Head().pos).sqrMagnitude;
}
}
void MoveMinions()
{
float headDistUnit = headDist / RADIUS;
for (int i = 1; i < minions.Count; i++)
{
Minion minion = minions[i];
// Move minion on the path
minion.MoveOnPath(path, headDistUnit);
// Extra push to avoid minions stepping on each other
Vector2 prevToNext = minions[i - 1].transform.position - minion.transform.position;
float distance = prevToNext.magnitude;
if (distance < RADIUS)
{
float intersection = RADIUS - distance;
minion.Push(-prevToNext.normalized * RADIUS * intersection);
}
}
}
}
Path 是一个环形缓冲区,Head()
给你最新添加的点,你可以使用 Head(index)
获取头部并将其偏移到一个方向(+/-)。 Minions 使用它来获取头部后面的点:path.Head(-1)
。
public class Path
{
public Vector2[] Points { get; private set; }
public int Capacity => Points.Length;
int head;
public Path(int capacity)
{
head = 0;
Points = new Vector2[capacity];
}
public void Resize()
{
Vector2[] temp = new Vector2[Capacity * 2];
for (int i = 0; i < temp.Length; i++)
{
temp[i] = i < Capacity ? Head(i + 1) : Tail();
}
head = Capacity - 1;
Points = temp;
}
public void Add(Vector2 pos)
{
int prev = Mod(head, Capacity);
Next();
int next = Mod(head, Capacity);
Points[next].pos = pos;
}
public Vector2 Head()
{
return Points[head];
}
public Vector2 Head(int index)
{
return Points[Mod(head + index, Capacity)];
}
public Vector2 Tail()
{
return Points[Mod(head + 1, Capacity)];
}
public Vector2 Tail(int index)
{
return Points[Mod(head + 1 + index, Capacity)];
}
void Next()
{
head++;
head %= Capacity;
}
int Mod(int x, int m)
{
return (x % m + m) % m;
}
}
一个 minion 包含一个索引,它告诉我们 minion 在蛇中的位置(第一、第二、第三)。我们使用此索引来获取插值所需的两个点。 path.Head(-0)
将为我们提供领导者的观点。 path.Head(-1)
会给我们第一个小兵的点数。
public class Minion : MonoBehaviour
{
int index;
public Init(int index)
{
this.index = index;
}
// Move the minion along the path
public void MoveOnPath(Path path, float dist)
{
Vector2 prev = path.Head(-index);
Vector2 next = path.Head(-index + 1);
// Interpolate the position of the minion between the previous and the next point within the path. 'dist' is the distance between the 'head' of the path and the leader
this.transform.position = Vector2.Lerp(prev.pos, next.pos, dist);
}
// Push the minion to avoid minions stepping on each other
public void Push(Vector2 dir)
{
this.transform.position += (Vector3)dir;
}
}
为了简化示例,我删除了很多代码。我希望您了解基本概念并能够实现自己的解决方案。
关于c# - 团结跟随领导行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57538286/
我试图在我的数据库中找到所有关注该用户的用户。 followers 集合有 3 个字段:_id、_t、_f。 当一个用户关注另一个用户时,它会将他们的用户 ID 添加到 _f 并将目标用户的 ID 添
我有一个 UICollectionView,它由单元格中的 UIImagePickerControl 按钮填充,我希望跟随 Collection View 末尾的单元格通过屏幕,但仍允许用户滚动 -
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 个月前。 Improv
好的,所以我知道如何将文本剪裁成特定的几何形状,但是文本不会根据剪裁自动换行,那么如果您有“勾选”作为几何/路径? 是否需要手动添加适合每一行的文本框,然后根据适合/不适合的内容拆分文本? 最佳答案
我里面有链接 s,但我在所有 上也有一个点击事件s。代码如下所示: $( document ).ready( function() { $( 'td.event' ).click( func
短版: 是)我有的: 2 元组列表,例如 [("a", "b"), ("b", "c"), ("d", "e"), ("c", "d"), ("f", "g")]不一定按字母顺序排列 我想要的是: 给
我正在尝试使用 xpath 来获取表的内容。 表格看起来像这样 Stuff Contents Contents Stuff
我有几个像这样的div: My Link 问题是,如果用户单击 div 而不是文本,则链接不会触发。这是我到目前为止所拥有的: $('#TopMenuBar .MenuList').click
我想要做一个链接到这个 .after() 的 .fadeIn() 动画,但这似乎不是这样做的方法。有什么建议吗? $(clicked_item).parent().parent().parent().
int getIdForSong(Song song){ String selectQuery = "SELECT id FROM " + TABLE_SONG + " WHERE " + S
现在右侧的 div 一直跟随滚动。如果我想让它在页面滚动到div的顶部时开始跟随滚动,并在向上滚动时让它保持在那里,我还需要做什么? jsfiddle $(window).scroll(functio
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and t
我正在为我的客户设计一件 T 恤,我使用 html5 Canvas 制作了它。衬衫设计师现在已经完成,但他要求我添加一个放大镜(类似这样的东西:http://mlens.musings.it/)。我在
我正在尝试调试远程主机上的 fork 进程,但每次都让 gdbserver 进程在子退出时结束。 尝试在 .gdbinit 中设置“set follow-fork-mode child”,没有帮助。
我正在制作一个带有滚动控件的响应式菜单。我有一个小问题,我的渐变和控件跟随,滚动时,你可以在我的 JSFiddle 中看到它. 我的菜单控件有我的 CSS #page .page-nav .contr
我将我的页面分为左右两部分。我用 div 来制作左导航和右导航。在右侧导航中,我也有多个 div。现在,当我向下滚动页面时,只有页面的右侧部分正在滚动,而左侧导航则停留在那里。 所以当我向下滚动页面时
我刚刚开始使用 svg 和 anime.js。我正在尝试重新创建 svg motion path在文档中找到我自己的 Assets 。不过,我没有使用 div 来跟随路径,而是使用了另一条路径。 我有
我将展示整个代码,但请注意指针上方的引号,因为我将在那里讨论我的问题。我会在引用评论中告诉你我认为那里发生了什么。代码编译并运行,我只需要帮助理解部分代码。 #include #include i
我在左侧有一个 div,其中包括营业时间和天气。我希望该 div 根据用户的滚动方式向下和向上滚动。所以它会跟随页面上下移动。我将如何尝试呢?这是我的网站judystropicalgarden.com
所以我遇到了这个小问题,我的相机错误地固定在播放器上。 左上角的蓝色 Sprite 是玩家,但它应该位于屏幕中央。关于这个问题的所有其他线程都使用固定渲染管道,而我使用基于 VBO 的线程。 我的矩阵
我是一名优秀的程序员,十分优秀!