public Vector3 GetSteering(ICollection <Rigidbody> targets) { Vector3 acceleration = Vector3.zero; // 只要存在发生碰撞的就要想办法分离 foreach (Rigidbody r in targets) { /* 远离的方向 */ Vector3 direction = transform.position - r.position; float dist = direction.magnitude; if (dist < maxSepDist) { float targetRadius = SteeringBasics.GetBoundingRadius(r.transform); /* 计算分离强度(可改为使用平方反比,而不是线性) */ var strength = sepMaxAcceleration * (maxSepDist - dist) / (maxSepDist - boundingRadius - targetRadius); /* 将分离加速度增加到现有的 Steer 上 (因为可能不是跟一个发生碰撞) */ direction.Normalize(); acceleration += direction * strength; } } return(acceleration); }
void Start() { // 得到屏幕大小 float z = -1 * Camera.main.transform.position.z; bottomLeft = Camera.main.ViewportToWorldPoint(new Vector3(0, 0, z)); Vector3 topRight = Camera.main.ViewportToWorldPoint(new Vector3(1, 1, z)); widthHeight = topRight - bottomLeft; // 如果需要的话 要避免和场景内其他对象重叠 纪录他们的数据 thingsToAvoidRadius = new float[thingsToAvoid.Length]; for (int i = 0; i < thingsToAvoid.Length; i++) { thingsToAvoidRadius[i] = SteeringBasics.GetBoundingRadius(thingsToAvoid[i].transform); } // 创建就行了 for (int i = 0; i < numberOfObjects; i++) { // 每次不一定创建成功,这里增加概率 for (int j = 0; j < 10; j++) { if (TryToCreateObject()) { break; } } } }
/// <summary> /// 判断是否可以放置, 主要判断是否重叠 /// </summary> /// <param name="halfSize"></param> /// <param name="pos"></param> /// <returns></returns> private bool CanPlaceObject(float halfSize, Vector3 pos) { // 确保它不会与任何东西重叠 for (int i = 0; i < thingsToAvoid.Length; i++) { float dist = Vector3.Distance(thingsToAvoid[i].position, pos); if (dist < halfSize + thingsToAvoidRadius[i]) { return(false); } } //确保它不会与任何现有对象重叠 foreach (Rigidbody o in objs) { float dist = Vector3.Distance(o.position, pos); float oRadius = SteeringBasics.GetBoundingRadius(o.transform); if (dist < oRadius + spaceBetweenObjects + halfSize) { return(false); } } return(true); }
// 获取隐藏位置 private Vector3 GetHidingPosition(Rigidbody obstacle, Rigidbody target) { // 这个障碍物 附近 float distAway = SteeringBasics.GetBoundingRadius(obstacle.transform) + distanceFromBoundary; // 目标看障碍物的方向(就要躲在这个方向上) Vector3 dir = obstacle.position - target.position; dir.Normalize(); // 最终隐藏位置 return(obstacle.position + dir * distAway); }
public Vector3 GetSteering(ICollection <Rigidbody> targets) { Vector3 acceleration = Vector3.zero; /* 1. 找出这个角色将会与之碰撞的第一个目标 */ /* 第一次碰撞时间 */ float shortestTime = float.PositiveInfinity; // 正无穷大 临时值 /* The first target that will collide and other data that * we will need and can avoid recalculating */ // 重置数据 ,并且可以避免重新计算 Rigidbody firstTarget = null; //float firstMinSeparation = 0, firstDistance = 0; float firstMinSeparation = 0, firstDistance = 0, firstRadius = 0; Vector3 firstRelativePos = Vector3.zero, firstRelativeVel = Vector3.zero; foreach (Rigidbody r in targets) { /* 计算碰撞时间 */ // 相差位置 Vector3 relativePos = transform.position - r.position; // 相差速度 Vector3 relativeVel = rb.velocity - r.velocity; // 标量 float distance = relativePos.magnitude; float relativeSpeed = relativeVel.magnitude; // 说明朝着相反的方向运动 并且速度一样 if (relativeSpeed == 0) { continue; } // float timeToCollision = -1 * Vector3.Dot(relativePos, relativeVel) / (relativeSpeed * relativeSpeed); /* 检查它们是否会碰撞 */ Vector3 separation = relativePos + relativeVel * timeToCollision; float minSeparation = separation.magnitude; float targetRadius = SteeringBasics.GetBoundingRadius(r.transform); // 两者分离了 if (minSeparation > characterRadius + targetRadius) //if (minSeparation > 2 * agentRadius) { continue; } /* 检查它是否是最短, 是的话就纪录最短的 */ if (timeToCollision > 0 && timeToCollision < shortestTime) { shortestTime = timeToCollision; firstTarget = r; firstMinSeparation = minSeparation; firstDistance = distance; firstRelativePos = relativePos; firstRelativeVel = relativeVel; firstRadius = targetRadius; } } /* 2. 计算加速度 */ /* 如果没有目标,就退出 */ if (firstTarget == null) { return(acceleration); } /* If we are going to collide with no separation or if we are already colliding then * Steer based on current position */ // 如果我们要在没有分离的情况下发生碰撞,或者如果我们已经碰撞了,然后根据当前位置进行碰撞 if (firstMinSeparation <= 0 || firstDistance < characterRadius + firstRadius) //if (firstMinSeparation <= 0 || firstDistance < 2 * agentRadius) { acceleration = transform.position - firstTarget.position; } /* 计算未来的相对位置 */ else { acceleration = firstRelativePos + firstRelativeVel * shortestTime; } /* 远离目标 */ acceleration.Normalize(); acceleration *= maxAcceleration; return(acceleration); }
void Start() { characterRadius = SteeringBasics.GetBoundingRadius(transform); rb = GetComponent <Rigidbody>(); }
// Use this for initialization void Start() { boundingRadius = SteeringBasics.GetBoundingRadius(transform); }