예제 #1
0
    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);
    }
예제 #2
0
    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;
                }
            }
        }
    }
예제 #3
0
    /// <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);
    }
예제 #4
0
    // 获取隐藏位置
    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);
    }
예제 #5
0
    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);
    }
예제 #6
0
    void Start()
    {
        characterRadius = SteeringBasics.GetBoundingRadius(transform);

        rb = GetComponent <Rigidbody>();
    }
예제 #7
0
 // Use this for initialization
 void Start()
 {
     boundingRadius = SteeringBasics.GetBoundingRadius(transform);
 }