コード例 #1
0
        public void OnDisable()
        {
            Pathfinding.RVO.Simulator sim         = AStarPathfindingUtils.GetSimulator();
            RVOContourObstacle        cutObstacle = GetRVOContourObstacle();

            if (cutObstacle)
            {
                cutObstacle.RemoveDynamicObstacles(sim);
            }

            if (_wasActive)
            {
                if (cutObstacle)
                {
                    cutObstacle.SetObstaclesActive(sim, false);
                }

                if (null != TileHandlerHelper.instance)
                {
                    TileHandlerHelper.instance.OnNavMeshCutDisabled(lastBounds);
                }
            }
            _UpdateIsRequired = false;
            EventManager.instance.RemoveListener <PopulateZonesPlayingEvent>(OnPopulateZones);
            EventManager.instance.RemoveListener <LevelStartEvent>(OnLevelStart);
        }
コード例 #2
0
    public static List <TriangleMeshNode> GetAllNodesInRadius(Vector3 origin, float radius)
    {
        //float radiusSquared = radius * radius;

        TriangleMeshNode root = AStarPathfindingUtils.GetNearestNodeOnNavMesh(origin);

        List <TriangleMeshNode> validNodes = new List <TriangleMeshNode>();

        EB.Collections.Queue <TriangleMeshNode> toCheck = new EB.Collections.Queue <TriangleMeshNode>();
        HashSet <TriangleMeshNode> visited = new HashSet <TriangleMeshNode>();

        toCheck.Enqueue(root);
        while (toCheck.Count > 0)
        {
            TriangleMeshNode curNode = toCheck.Dequeue();

            if (SphereXZTriangleIntersect(origin, radius, (Vector3)curNode.GetVertex(0), (Vector3)curNode.GetVertex(1), (Vector3)curNode.GetVertex(2)))
            {
                validNodes.Add(curNode);
                for (int i = 0; i < curNode.connections.Length; i++)
                {
                    TriangleMeshNode connection = curNode.connections[i] as TriangleMeshNode;
                    if (!visited.Contains(connection))
                    {
                        toCheck.Enqueue(connection);
                    }
                }
            }

            visited.Add(curNode);
        }

        return(validNodes);
    }
コード例 #3
0
        public void NotifyUpdated()
        {
#if BNICKSON_UPDATED
            Pathfinding.RVO.Simulator sim         = AStarPathfindingUtils.GetSimulator();
            RVOContourObstacle        cutObstacle = GetRVOContourObstacle();
            if (cutObstacle)
            {
                cutObstacle.SetObstaclesActive(sim, isActive);
                if (HasMoved())
                {
                    cutObstacle.Move(sim);
                }
                else if (_UpdateIsRequired && isActive)
                {
                    cutObstacle.CreateDynamicEdgesIfNoStaticEdgesExist(sim);
                }
            }

            _wasActive        = isActive;
            _UpdateIsRequired = false;
#endif
            wasEnabled = enabled;

            if (wasEnabled)
            {
                lastPosition = tr.position;
                lastBounds   = GetBounds();

                if (useRotation)
                {
                    lastRotation = tr.rotation;
                }
            }
        }
コード例 #4
0
 private Pathfinding.RVO.Simulator GetSimulator()
 {
     if (null == _sim)
     {
         _sim = AStarPathfindingUtils.GetSimulator();
     }
     return(_sim);
 }
コード例 #5
0
    // calculate what position and velocity we should send to peers who do not own the characters
    public void CalculatePositionAndVelocityToSend(ref Vector2 position, ref Vector2 velocity, ref float distToDestination)
    {
        // to save some bandwidth we're sending 2d vectors. y is calculated procedurally based on the ground height at the point you are standing on so isn't needed to be sent
        position.x = transform.position.x;
        position.y = transform.position.z;
        Vector3 velocity3d = new Vector3(_rvoController.newVelocity.x, 0f, _rvoController.newVelocity.z);

        Vector3 positionToDestinationXZ = GameUtils.SubXZ(_locomotion.Destination, transform.position);

        distToDestination = Mathf.Max(positionToDestinationXZ.magnitude - _locomotion.ArrivalThreshold, 0f);
        // check if our current rvo controller velocity is gonna make us overshoot the target
        if (velocity3d.magnitude * GetNetworkUpdateInterval() > distToDestination)
        {         // set our speed so we do not overshoot
            velocity3d = velocity3d.normalized * (distToDestination / GetNetworkUpdateInterval());
        }

        const float DirectionTolerance = 0.819f; // 0.819f == cos(35 degrees)
        const float StoppingTime       = 4f;     // seconds

        // if the character is not heading towards the destination, or the destination is far away then it's not gonna stop soon and the distance can be unlimited
        if (GameUtils.DotXZ(velocity3d.normalized, positionToDestinationXZ.normalized) < DirectionTolerance || // character is not traveling towards target (probably RVO related)
            distToDestination > velocity3d.magnitude * GetNetworkUpdateInterval() * StoppingTime)              // the destination is far away, so no stop is imminent
        {
            distToDestination = NetworkTransform.DistanceUnlimited;
        }

        // this section makes sure our velocity would not take us off the nav mesh
        Vector3 from           = transform.position;
        Vector3 targetPosition = AStarPathfindingUtils.CalculateExitPoint(ref from, from + velocity3d, _locomotion.Simulator, true);         // see if the target poition would cause us to exit the nav mesh

        float distToOriginalTargetSqr = GameUtils.GetDistSqXZ(from, from + velocity3d);
        float distToNewTargetSqr      = GameUtils.GetDistSqXZ(from, targetPosition);

        if (distToNewTargetSqr < distToOriginalTargetSqr)         // if the returned length is nearer, it means we hit an edge
        {
            const float NudgeIntoNavMeshDist = 0.1f;
            if (distToNewTargetSqr > NudgeIntoNavMeshDist * NudgeIntoNavMeshDist)
            {
                float distToNewTarget = Mathf.Sqrt(distToNewTargetSqr);
                // here we're moving targetPosition slightly back onto the nav mesh away from the nav mesh perimeter, this is to stop the character being moved slightly off mesh
                targetPosition = from + (((targetPosition - from) / distToNewTarget) * (distToNewTarget - NudgeIntoNavMeshDist));
            }
            else
            {
                targetPosition = from;                 // edge is very close, so just use the from position as the target position
            }
            velocity3d = targetPosition - transform.position;
        }
        velocity.x = velocity3d.x;
        velocity.y = velocity3d.z;

        if (!NetworkTransform.IsMovement(new Vector3(velocity3d.x, 0f, velocity3d.z))) // is no movement being sent
        {                                                                              // if we're sending a velocity of zero, we can have distance unlimited because there will be no movement anyway, so having distance unlimited means it can start moving quickly when a movement begins
            distToDestination = NetworkTransform.DistanceUnlimited;
        }
    }
コード例 #6
0
        public void OnPopulateZones(PopulateZonesPlayingEvent evt)
        {
            if (isActive != _wasActive)             // if our active state has changed, it means we are awaiting for the fact this has hapenned to be picked up in the TileHandlerHelper Update
            {
                lastPosition = tr.position;         // set this here so TileHandlerHelper picks up the activity change, and not the movement, so NotifyUpdated() will not flag
                // this cuts obstacles as dynamic
            }
            RVOContourObstacle cutObstacle = GetRVOContourObstacle();

            cutObstacle.OnLatePostScan(AStarPathfindingUtils.GetSimulator());
        }
コード例 #7
0
    public void OnPopulateZones(PopulateZonesPlayingEvent evt)
    {
        if (scanOnStartup && AStarPathfindingUtils.WillNavMeshBeBuiltFromInputMeshOnLevelBegin())
        {
            if (!astarData.cacheStartup || astarData.data_cachedStartup == null)
            {
                LevelHelper helper = GameObject.FindObjectOfType(typeof(LevelHelper)) as LevelHelper;
                if (helper != null)
                {
                    AStarPathfindingUtils.CreateRecastNavMeshForInputMeshes(helper.transform.Find(ZoneHelper.ZonesRootName), helper.isOverworldNavMeshRequired);
                    Scan();
                    EventManager.instance.Raise(new NavMeshScanEvent());
                }
            }
        }

        if (Application.isPlaying)
        {
            RecastGraph.DestroyWalkableAreaObjects();     // we don't need the instances of AStarPathfindingWalkableArea in the game after this point
            RecastGraph.DestroyRecastMeshObjComponents(); // RecastMeshObj's are only used for nav mesh generation, they are not needed after this point
            AStarPathfindingRecastCut.DestroyRecastCutObjects();
            AStarPathfindingGenerationTimeGeo.DestroyGenerationTimeGeoObjects();
        }
    }
コード例 #8
0
        // make sure everything is correct on level start
        public void OnLevelStart(LevelStartEvent e)
        {
            RVOContourObstacle cutObstacle = GetRVOContourObstacle();

            cutObstacle.SetObstaclesActive(AStarPathfindingUtils.GetSimulator(), isActive);
        }
コード例 #9
0
    private bool FindTargetAndLocation(TouchWrapper touch, out Transform target, out Vector3 location, out Vector3 groundPosition, out Vector3 direction)
    {
        target = null;

        if (Camera.main == null)
        {
            location       = default(Vector3);
            groundPosition = default(Vector3);
            direction      = default(Vector3);
            return(false);
        }
        if (mMainCamera == null)
        {
            mMainCamera = Camera.main;
        }

        Ray        ray = mMainCamera.ScreenPointToRay(new Vector3(Mathf.Clamp(touch.position.x, 0, Screen.width), Mathf.Clamp(touch.position.y, 0, Screen.height), 0.0f));
        RaycastHit rayHit;

        groundPosition = default(Vector3);
        direction      = default(Vector3);
        location       = default(Vector3);

        if (Physics.Raycast(ray, out rayHit, 200, _groundLayer))
        {
            groundPosition = rayHit.point;
        }

        //Check raycast first for best precision
        if (Physics.Raycast(ray, out rayHit, 200, _characterLayers | _groundLayer))
        {
            if (PlayerManager.IsPlayer(rayHit.transform.gameObject))
            {
                target = rayHit.transform;
            }
            else if (rayHit.transform.gameObject.layer != LayerMask.NameToLayer("Ground"))
            {
                Selectable selectable = rayHit.transform.GetComponent <Selectable>();
                if (selectable == null)
                {
                    //If raycast couldn't find a selectable widen to an overlap sphere cast and pick closest selectable
                    Collider[] colliders = Physics.OverlapSphere(rayHit.point, fingerRadius, 1 << LayerMask.NameToLayer("Enemy"));
                    if (colliders.Length > 0)
                    {
                        float    minSqDistance   = float.MaxValue;
                        Collider closestCollider = colliders[0];
                        foreach (Collider collider in colliders)
                        {
                            float sqrDistance = Vector3.SqrMagnitude(collider.transform.position - rayHit.point);
                            if (sqrDistance < minSqDistance)
                            {
                                minSqDistance   = sqrDistance;
                                closestCollider = collider;
                            }
                        }
                        selectable = closestCollider.gameObject.GetComponent <Selectable>();
                    }
                }

                //Move or target selectable
                if (selectable != null)
                {
                    target = selectable.transform;
                }
                else
                {
                    target = null;
                }
            }

            //if the object has a ServerCallback then call it!!
            if (rayHit.transform.gameObject != null)
            {
                MeshClick callback = rayHit.transform.gameObject.GetComponent <MeshClick>();
                if (callback != null)
                {
                    target = callback.transform;
                }
            }


            if (target != null)
            {
                location = target.transform.position;
            }
            else
            {
                location = groundPosition;
            }

            if (_playerTransform != null && _muzzleTransform != null)
            {
                Vector3 muzzleYOffset = new Vector3(0, _muzzleTransform.position.y - _playerTransform.position.y, 0);
                location += muzzleYOffset;
                direction = (groundPosition - _playerTransform.position).normalized;
            }

            // todo: FindTargetAndLocation called many times
            //Debug.LogFormat("FindTargetAndLocation: location = {0}", location.ToString());
            if (!AStarPathfindingUtils.IsPointOnNavMeshOptimized(location))
            {
                return(false);
            }

            return(true);
        }
        else if (_playerTransform != null)
        {
            Plane playerPlane = new Plane(Vector3.up, _playerTransform.position);
            float enter       = 0;
            if (playerPlane.Raycast(ray, out enter))
            {
                Vector3 hitPoint = ray.GetPoint(enter);
                direction      = (hitPoint - _playerTransform.position).normalized;
                groundPosition = hitPoint;
            }
        }

        target   = null;
        location = default(Vector3);
        return(false);
    }
コード例 #10
0
    /** Sets up all needed variables and scans the graphs.
     * Calls Initialize, starts the ReturnPaths coroutine and scans all graphs.
     * Also starts threads if using multithreading
     * \see #OnAwakeSettings
     */
    void Awake()
    {
        //Very important to set this. Ensures the singleton pattern holds
        active = this;

        if (FindObjectsOfType(typeof(AstarPath)).Length > 1)
        {
            EB.Debug.LogError("You should NOT have more than one AstarPath component in the scene at any time.\n" +
                              "This can cause serious errors since the AstarPath component builds around a singleton pattern.");
        }

        //Disable GUILayout to gain some performance, it is not used in the OnGUI call
        useGUILayout = false;

        isEditor = Application.isEditor;

        // This class uses the [ExecuteInEditMode] attribute
        // So Awake is called even when not playing
        // Don't do anything when not in play mode
        if (!Application.isPlaying)
        {
            return;
        }

        if (OnAwakeSettings != null)
        {
            OnAwakeSettings();
        }

        //To make sure all graph modifiers have been enabled before scan (to avoid script run order issues)
        GraphModifier.FindAllModifiers();
        RelevantGraphSurface.FindAllGraphSurfaces();

        int numThreads = CalculateThreadCount(threadCount);


        threads = new Thread[numThreads];

        //Thread info, will contain at least one item since the coroutine "thread" is thought of as a real thread in this case
        threadInfos = new PathThreadInfo[System.Math.Max(numThreads, 1)];

        //Set up path queue with the specified number of receivers
        pathQueue = new ThreadControlQueue(threadInfos.Length);

        for (int i = 0; i < threadInfos.Length; i++)
        {
            threadInfos[i] = new PathThreadInfo(i, this, new PathHandler(i, threadInfos.Length));
        }

        //Start coroutine if not using multithreading
        if (numThreads == 0)
        {
            threadEnumerator = CalculatePaths(threadInfos[0]);
        }
        else
        {
            threadEnumerator = null;
        }

#if !UNITY_WEBGL
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i]              = new Thread(new ParameterizedThreadStart(CalculatePathsThreaded));
            threads[i].Name         = "Pathfinding Thread " + i;
            threads[i].IsBackground = true;
        }

        //Start pathfinding threads
        for (int i = 0; i < threads.Length; i++)
        {
            if (logPathResults == PathLog.Heavy)
            {
                EB.Debug.Log("Starting pathfinding thread {0}", i);
            }
            threads[i].Start(threadInfos[i]);
        }

        if (numThreads != 0)
        {
            graphUpdateThread = new Thread(new ParameterizedThreadStart(ProcessGraphUpdatesAsync));
            graphUpdateThread.IsBackground = true;

            // Set the thread priority for graph updates
            // Unless compiling for windows store or windows phone which does not support it
#if !UNITY_WINRT
            graphUpdateThread.Priority = System.Threading.ThreadPriority.Lowest;
#endif
            graphUpdateThread.Start(this);
        }
#endif

        Initialize();

        // Flush work items, possibly added in initialize to load graph data
        FlushWorkItems();

        euclideanEmbedding.dirty = true;

#if BNICKSON_UPDATED
        // added !AStarPathfindingUtils.WillNavMeshBeBuiltFromInputMeshOnLevelBegin()
        if (scanOnStartup && !AStarPathfindingUtils.WillNavMeshBeBuiltFromInputMeshOnLevelBegin())
#else
        if (scanOnStartup)
#endif
        {
            if (!astarData.cacheStartup || astarData.file_cachedStartup == null)
            {
                Scan();

#if BNICKSON_UPDATED
                EventManager.instance.Raise(new NavMeshScanEvent());
#endif
            }
        }
    }