Пример #1
0
    public bool Step()
    {
        if (m_Target != null && m_Unit != null)
        {
            UnitMover unitMover = m_Unit.GetComponentInChildren<UnitMover>();
            float halfwidth = unitMover.parentUnit.Files * 0.5f;
            if (m_DataNodes.Count == 0)
            {
                Vector3 unitForward = m_Unit.transform.forward;
                Vector3 unitSide = m_Unit.transform.right;
                Vector3 unitPos = unitMover.parentUnit.transform.position;
                AIDataNode newNode = new AIDataNode();

                //attempt move forward

                int check = AddForward(unitPos, unitForward, halfwidth);
                if (check >= 1)
                {
                    newNode = new AIDataNode();
                    newNode.m_MoveType = MoveType.MoveForward;
                    newNode.m_CostSoFar = m_BaseMove;
                    newNode.m_Parent = null;
                    newNode.m_Position = unitPos + unitForward * m_BaseMove;
                    newNode.m_Forward = unitForward;
                    newNode.m_MoveAmount = m_BaseMove;
                    newNode.m_CurrentAngleRad = unitMover.currentRotationAngle;
                    newNode.m_DistanceToGoal = Vector3.Distance(m_Target.transform.position, newNode.m_Position);
                    newNode.CalcFCost();
                    bool shouldAdd = true;
                    foreach (AIDataNode close in m_ClosedList)
                    {
                        if (Vector3.Distance(newNode.m_Position, close.m_Position) < 0.00001f && newNode.m_CurrentAngleRad - close.m_CurrentAngleRad < 0.00001f)
                            shouldAdd = false;
                    }
                    if (shouldAdd)
                        m_DataNodes.AddFirst(newNode);
                }
                if(check == 2)
                {
                    HitTarget(newNode);
                    return true;
                }
                //Debug.Log("WTF " + check.ToString());

                //check if a turn CCW is possible
                float curAngle = unitMover.currentRotationAngle;

                Vector3 newPos, newForward;
                float nextAngle;
                check = AddCounterClockwise(unitPos, unitSide, halfwidth, curAngle, out newPos, out newForward, out nextAngle);
                if (check >= 1)
                {
                    newNode = new AIDataNode();
                    newNode.m_MoveType = MoveType.RotateCounterClockwise;
                    newNode.m_CostSoFar = (m_BaseRotate * Mathf.Rad2Deg) / 18.0f;
                    newNode.m_Parent = null;
                    newNode.m_Position = newPos;
                    newNode.m_Forward = newForward;
                    newNode.m_MoveAmount = m_BaseRotate * Mathf.Rad2Deg;
                    newNode.m_CurrentAngleRad = nextAngle;
                    newNode.m_DistanceToGoal = Vector3.Distance(m_Target.transform.position, newNode.m_Position);
                    newNode.CalcFCost();
                    bool shouldAdd = true;
                    foreach(AIDataNode close in m_ClosedList)
                    {
                        if (Vector3.Distance(newNode.m_Position, close.m_Position) < 0.00001f && newNode.m_CurrentAngleRad - close.m_CurrentAngleRad < 0.00001f)
                            shouldAdd = false;
                    }
                    if(shouldAdd)
                        m_DataNodes.AddFirst(newNode);
                }
                if (check == 2)
                {
                    HitTarget(newNode);
                    return true;
                }

                //check if a turn CW is possible
                check = AddClockwise(unitPos, unitSide, halfwidth, curAngle, out newPos, out newForward, out nextAngle);
                if (check >= 1)
                {
                    newNode = new AIDataNode();
                    newNode.m_MoveType = MoveType.RotateClockwise;
                    newNode.m_CostSoFar = (m_BaseRotate * Mathf.Rad2Deg) / 18.0f;
                    newNode.m_Parent = null;
                    newNode.m_Position = newPos;
                    newNode.m_Forward = newForward;
                    newNode.m_MoveAmount = m_BaseRotate * Mathf.Rad2Deg;
                    newNode.m_CurrentAngleRad = nextAngle;
                    newNode.m_DistanceToGoal = Vector3.Distance(m_Target.transform.position, newNode.m_Position);
                    newNode.CalcFCost();
                    bool shouldAdd = true;
                    foreach (AIDataNode close in m_ClosedList)
                    {
                        if (Vector3.Distance(newNode.m_Position, close.m_Position) < 0.00001f && newNode.m_CurrentAngleRad - close.m_CurrentAngleRad < 0.00001f)
                            shouldAdd = false;
                    }
                    if (shouldAdd)
                        m_DataNodes.AddFirst(newNode);
                }
                if (check == 2)
                {
                    HitTarget(newNode);
                    return true;
                }
            }
            else
            {
                List<AIDataNode> newList = new List<AIDataNode>();
                int count = 0;
                AIDataNode newNode = new AIDataNode();
                while(m_DataNodes.Count > 0 && count < m_CountPerStep)
                {
                    count++;
                    AIDataNode node = m_DataNodes.First.Value;
                    m_DataNodes.RemoveFirst();
                    m_ClosedList.AddLast(node);

                    Vector3 unitForward = node.m_Forward;
                    Vector3 unitSide = Vector3.Cross(Vector3.up, unitForward).normalized;
                    Vector3 unitPos = node.m_Position;

                    int check = AddForward(unitPos, unitForward, halfwidth);
                    if (check >= 1)
                    {
                        newNode = new AIDataNode();
                        newNode.m_MoveType = MoveType.MoveForward;
                        newNode.m_CostSoFar = node.m_CostSoFar + m_BaseMove;
                        newNode.m_Parent = node;
                        newNode.m_Position = unitPos + unitForward * m_BaseMove;
                        newNode.m_Forward = unitForward;
                        newNode.m_MoveAmount = m_BaseMove;
                        newNode.m_CurrentAngleRad = node.m_CurrentAngleRad;
                        newNode.m_DistanceToGoal = Vector3.Distance(m_Target.transform.position, newNode.m_Position);
                        newNode.CalcFCost();
                        bool shouldAdd = true;
                        foreach (AIDataNode close in m_ClosedList)
                        {
                            if (Vector3.Distance(newNode.m_Position, close.m_Position) < 0.00001f && newNode.m_CurrentAngleRad - close.m_CurrentAngleRad < 0.00001f)
                                shouldAdd = false;
                        }
                        if (shouldAdd)
                            newList.Add(newNode);
                    }
                    if (check == 2)
                    {
                        HitTarget(newNode);
                        return true;
                    }

                    float curAngle = node.m_CurrentAngleRad;

                    Vector3 newPos, newForward;
                    float nextAngle;
                    check = AddCounterClockwise(unitPos, unitSide, halfwidth, curAngle, out newPos, out newForward, out nextAngle);
                    if (check >= 1)
                    {
                        newNode = new AIDataNode();
                        newNode.m_MoveType = MoveType.RotateCounterClockwise;
                        newNode.m_CostSoFar = node.m_CostSoFar + (m_BaseRotate * Mathf.Rad2Deg) / 18.0f;
                        newNode.m_Parent = node;
                        newNode.m_Position = newPos;
                        newNode.m_Forward = newForward;
                        newNode.m_MoveAmount = m_BaseRotate * Mathf.Rad2Deg;
                        newNode.m_CurrentAngleRad = nextAngle;
                        newNode.m_DistanceToGoal = Vector3.Distance(m_Target.transform.position, newNode.m_Position);
                        newNode.CalcFCost();
                        bool shouldAdd = true;
                        foreach (AIDataNode close in m_ClosedList)
                        {
                            if (Vector3.Distance(newNode.m_Position, close.m_Position) < 0.00001f && newNode.m_CurrentAngleRad - close.m_CurrentAngleRad < 0.00001f)
                                shouldAdd = false;
                        }
                        if (shouldAdd)
                            newList.Add(newNode);
                    }
                    if (check == 2)
                    {
                        HitTarget(newNode);
                        return true;
                    }

                    //check if a turn CW is possible
                    check = AddClockwise(unitPos, unitSide, halfwidth, curAngle, out newPos, out newForward, out nextAngle);
                    if (check >= 1)
                    {
                        newNode = new AIDataNode();
                        newNode.m_MoveType = MoveType.RotateClockwise;
                        newNode.m_CostSoFar = node.m_CostSoFar + (m_BaseRotate * Mathf.Rad2Deg) / 18.0f;
                        newNode.m_Parent = node;
                        newNode.m_Position = newPos;
                        newNode.m_Forward = newForward;
                        newNode.m_MoveAmount = m_BaseRotate * Mathf.Rad2Deg;
                        newNode.m_CurrentAngleRad = nextAngle;
                        newNode.m_DistanceToGoal = Vector3.Distance(m_Target.transform.position, newNode.m_Position);
                        newNode.CalcFCost();
                        bool shouldAdd = true;
                        foreach (AIDataNode close in m_ClosedList)
                        {
                            if (Vector3.Distance(newNode.m_Position, close.m_Position) < 0.00001f && newNode.m_CurrentAngleRad - close.m_CurrentAngleRad < 0.00001f)
                                shouldAdd = false;
                        }
                        if (shouldAdd)
                            newList.Add(newNode);
                    }
                    if (check == 2)
                    {
                        HitTarget(newNode);
                        return true;
                    }
                }
                foreach(AIDataNode node in newList)
                {
                    m_DataNodes.AddFirst(node);
                }
                SortDataNodes();
            }
        }
        return false;
    }
Пример #2
0
    public void CleanPath()
    {
        AIDataNode node = m_PathList[m_CleanIndex];

        UnitMover unitMover = m_Unit.GetComponentInChildren<UnitMover>();
        float halfwidth = unitMover.parentUnit.Files * 0.5f;
        Vector3 colliderOffset = new Vector3(0.0f, m_ColliderHeight) - node.m_Forward * 0.5f;
        Vector3 right = Vector3.Cross(Vector3.up, node.m_Forward).normalized;
        Vector3 tl = node.m_Position - right * halfwidth + colliderOffset;
        Vector3 tr = node.m_Position + right * halfwidth + colliderOffset;

        float maxValidDistance = 0.0f;
        AIDataNode validNode = null;
        int hitCorner = -1;
        Vector3 ctl = Vector3.zero, ctr = Vector3.zero;
        for(int i = m_CleanIndex + 1; i < m_PathList.Count; ++i)
        {
            AIDataNode checkNode = m_PathList[i];
            Vector3 cright = Vector3.Cross(Vector3.up, checkNode.m_Forward).normalized;
            ctl = checkNode.m_Position - right * halfwidth + colliderOffset;
            ctr = checkNode.m_Position + right * halfwidth + colliderOffset;

            float checkDistance = Vector3.Distance(node.m_Position, checkNode.m_Position);
            RaycastHit hitObj;
            if (Physics.SphereCast(node.m_Position, m_ColliderRadius, checkNode.m_Position - node.m_Position, out hitObj, checkDistance))
            {
                //Debug.Log(hitObj.collider.tag + " was hit pos when trying to optimize path " + i.ToString());
                hitCorner = 0;
                break;
            }
            else if (Physics.SphereCast(tr, m_ColliderRadius, ctr - tr, out hitObj, checkDistance))
            {
                //Debug.Log(hitObj.collider.tag + " was hit tr when trying to optimize path " + i.ToString());
                hitCorner = 1;
                break;
            }
            else if (Physics.SphereCast(tl, m_ColliderRadius, ctl - tl, out hitObj, checkDistance))
            {
                //Debug.Log(hitObj.collider.tag + " was hit tl when trying to optimize path " + i.ToString());
                hitCorner = 2;
                break;
            }
            else
            {
                validNode = checkNode;
                maxValidDistance = checkDistance;
            }
        }
        Debug.Log("Hit corner = " + hitCorner.ToString());
        pathShorterStart = node;
        pathShorterEnd = validNode;
        optCorner = hitCorner;

        if (optCorner == 1)
        {
            Vector3 angle = (ctl - tl).normalized;
            float angleRad = Mathf.Atan2(angle.z, angle.x) - Mathf.PI * 0.5f;
            // calc start turn node vals
            Vector3 newRight = (new Vector3(Mathf.Cos(angleRad), 0.0f, Mathf.Sin(angleRad))).normalized;
            Vector3 posChange = (node.m_Position + right * halfwidth) - (node.m_Position + newRight * halfwidth);
            // create start turn node
            AIDataNode startTurn = new AIDataNode();
            startTurn.m_CostSoFar = node.m_CostSoFar + Mathf.Abs(angleRad) * Mathf.Rad2Deg;
            startTurn.m_CurrentAngleRad = angleRad;
            startTurn.m_Position = node.m_Position + posChange;
            startTurn.m_DistanceToGoal = Vector3.Distance(startTurn.m_Position, m_Target.transform.position);
            startTurn.m_Forward = Vector3.Cross(newRight, Vector3.up).normalized;
            startTurn.m_MoveType = (angleRad < 0.0f? MoveType.RotateClockwise : MoveType.RotateCounterClockwise);
            startTurn.m_Parent = node;                            // link parent of start turn node to be node
            startTurn.CalcFCost();
            // create straight path node
            AIDataNode straight = new AIDataNode();
            straight.m_CostSoFar = startTurn.m_CostSoFar + Vector3.Distance(ctl, tl);
            straight.m_CurrentAngleRad = startTurn.m_CurrentAngleRad;
            straight.m_Position = startTurn.m_Position + (ctl - tl);
            straight.m_DistanceToGoal = Vector3.Distance(straight.m_Position, m_Target.transform.position);
            straight.m_MoveAmount = Vector3.Distance(ctl, tl);
            straight.m_Forward = startTurn.m_Forward;
            straight.m_MoveType = MoveType.MoveForward;
            straight.m_Parent = startTurn;                         // link parent of straight path node to be start turn node
            straight.CalcFCost();
            // calc end turn vals
            angleRad = validNode.m_CurrentAngleRad - straight.m_CurrentAngleRad;
            newRight = (new Vector3(Mathf.Cos(angleRad), 0.0f, Mathf.Sin(angleRad))).normalized;
            posChange = (straight.m_Position + right * halfwidth) - (straight.m_Position + newRight * halfwidth);
            // create end turn node
            AIDataNode endTurn = new AIDataNode();
            endTurn.m_CostSoFar = straight.m_CostSoFar + Mathf.Abs(angleRad) * Mathf.Rad2Deg;
            endTurn.m_CurrentAngleRad = angleRad;
            endTurn.m_Position = straight.m_Position + posChange;
            endTurn.m_DistanceToGoal = Vector3.Distance(endTurn.m_Position, m_Target.transform.position);
            endTurn.m_Forward = Vector3.Cross(newRight, Vector3.up).normalized;
            endTurn.m_MoveType = (angleRad < 0.0f ? MoveType.RotateClockwise : MoveType.RotateCounterClockwise);
            endTurn.m_Parent = straight;                                // link parent of end turn node to be straight path node
            endTurn.CalcFCost();
            // link parent of valid node to be end turn node
            validNode.m_Parent = endTurn;
        }
        else if (optCorner == 2)
        {
            Vector3 angle = (ctr - tr).normalized;
            float angleRad = Mathf.Atan2(angle.z, angle.x) - Mathf.PI * 0.5f;
            // calc start turn node vals
            Vector3 newRight = (new Vector3(Mathf.Cos(angleRad), 0.0f, Mathf.Sin(angleRad))).normalized;
            Vector3 posChange = (node.m_Position + right * halfwidth) - (node.m_Position + newRight * halfwidth);
            // create start turn node
            AIDataNode startTurn = new AIDataNode();
            startTurn.m_CostSoFar = node.m_CostSoFar + Mathf.Abs(angleRad) * Mathf.Rad2Deg;
            startTurn.m_CurrentAngleRad = angleRad;
            startTurn.m_Position = node.m_Position + posChange;
            startTurn.m_DistanceToGoal = Vector3.Distance(startTurn.m_Position, m_Target.transform.position);
            startTurn.m_Forward = Vector3.Cross(newRight, Vector3.up).normalized;
            startTurn.m_MoveType = (angleRad < 0.0f ? MoveType.RotateClockwise : MoveType.RotateCounterClockwise);
            startTurn.m_Parent = node;                            // link parent of start turn node to be node
            startTurn.CalcFCost();
            // create straight path node
            AIDataNode straight = new AIDataNode();
            straight.m_CostSoFar = startTurn.m_CostSoFar + Vector3.Distance(ctl, tl);
            straight.m_CurrentAngleRad = startTurn.m_CurrentAngleRad;
            straight.m_Position = startTurn.m_Position + (ctr - tr);
            straight.m_DistanceToGoal = Vector3.Distance(straight.m_Position, m_Target.transform.position);
            straight.m_MoveAmount = Vector3.Distance(ctl, tl);
            straight.m_Forward = startTurn.m_Forward;
            straight.m_MoveType = MoveType.MoveForward;
            straight.m_Parent = startTurn;                         // link parent of straight path node to be start turn node
            straight.CalcFCost();
            // calc end turn vals
            angleRad = validNode.m_CurrentAngleRad - straight.m_CurrentAngleRad;
            newRight = (new Vector3(Mathf.Cos(angleRad), 0.0f, Mathf.Sin(angleRad))).normalized;
            posChange = (straight.m_Position + right * halfwidth) - (straight.m_Position + newRight * halfwidth);
            // create end turn node
            AIDataNode endTurn = new AIDataNode();
            endTurn.m_CostSoFar = straight.m_CostSoFar + Mathf.Abs(angleRad) * Mathf.Rad2Deg;
            endTurn.m_CurrentAngleRad = angleRad;
            endTurn.m_Position = straight.m_Position + posChange;
            endTurn.m_DistanceToGoal = Vector3.Distance(endTurn.m_Position, m_Target.transform.position);
            endTurn.m_Forward = Vector3.Cross(newRight, Vector3.up).normalized;
            endTurn.m_MoveType = (angleRad < 0.0f ? MoveType.RotateClockwise : MoveType.RotateCounterClockwise);
            endTurn.m_Parent = straight;                                // link parent of end turn node to be straight path node
            endTurn.CalcFCost();
            // link parent of valid node to be end turn node
            validNode.m_Parent = endTurn;
        }
        m_PathList = GetPath();
    }
Пример #3
0
 public void HitTarget(AIDataNode endPoint)
 {
     m_Path = endPoint;
     m_PathList = GetPath();
 }