bool RaycastRoad(out RaycastOutput raycastOutput)
        {
            RaycastInput raycastInput = new RaycastInput(Camera.main.ScreenPointToRay(Input.mousePosition), Camera.main.farClipPlane);
            raycastInput.m_netService.m_service = ItemClass.Service.Road;
            raycastInput.m_netService.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels;
            raycastInput.m_ignoreSegmentFlags = NetSegment.Flags.None;
            raycastInput.m_ignoreNodeFlags = NetNode.Flags.None;
            raycastInput.m_ignoreTerrain = true;

            return RayCast(raycastInput, out raycastOutput);
        }
Exemple #2
0
 public bool CastRay <T>(RaycastInput input, ref T collector) where T : struct, ICollector <RaycastHit>
 {
     return(Broadphase.CastRay(input, m_Bodies, ref collector));
 }
    protected override unsafe void OnUpdate()
    {
        Entities.ForEach(
            (ref CharacterControllerBody ccBodyComponentData,
             ref PhysicsCollider collider,
             ref PhysicsVelocity velocity,
             ref Translation position,
             ref Rotation rotation) =>
        {
            float3 up = math.up();

            ref PhysicsWorld world = ref World.Active.GetExistingManager <BuildPhysicsWorld>().PhysicsWorld;
            // movement and firing
            {
                float x = Input.GetAxis("Horizontal");
                float z = Input.GetAxis("Vertical");
                ccBodyComponentData.IsJumping = Input.GetButtonDown("Jump") && ccBodyComponentData.IsSupported;

                bool haveInput = (Mathf.Abs(x) > Mathf.Epsilon) || (Mathf.Abs(z) > Mathf.Epsilon);
                if (!haveInput)
                {
                    ccBodyComponentData.MovementVector = float3.zero;
                }
                else
                {
                    float3 movement = math.rotate(quaternion.RotateY(ccBodyComponentData.RotationAngle), new float3(x, 0, z));
                    ccBodyComponentData.MovementVector = math.normalize(movement);
                }

                if ((ccBodyComponentData.GunArmEntity != Entity.Null) && EntityManager.HasComponent <Rotation>(ccBodyComponentData.GunArmEntity))
                {
                    float a         = -Input.GetAxis("ShootY");
                    Rotation gunRot = EntityManager.GetComponentData <Rotation>(ccBodyComponentData.GunArmEntity);
                    gunRot.Value    = math.mul(gunRot.Value, quaternion.Euler(math.radians(a), 0, 0));
                    EntityManager.SetComponentData(ccBodyComponentData.GunArmEntity, gunRot);

                    if (EntityManager.HasComponent <PhysicsGun>(ccBodyComponentData.GunArmEntity))
                    {
                        var gunFire      = EntityManager.GetComponentData <PhysicsGun>(ccBodyComponentData.GunArmEntity);
                        gunFire.isFiring = Input.GetButton("Fire1")? 1 : 0;
                        EntityManager.SetComponentData(ccBodyComponentData.GunArmEntity, gunFire);
                    }
                }
            }

            // Rotate
            {
                float x        = Input.GetAxis("ShootX");
                bool haveInput = (Mathf.Abs(x) > Mathf.Epsilon);
                if (haveInput)
                {
                    ccBodyComponentData.RotationAngle += x * ccBodyComponentData.RotationSpeed * Time.deltaTime;
                }

                rotation.Value = quaternion.AxisAngle(math.up(), ccBodyComponentData.RotationAngle);
            }

            // check supported
            {
                float3 rayStart = position.Value;
                float3 rayEnd   = rayStart + (ccBodyComponentData.CharacterHeight * -math.up());
                float3 rayDir   = rayEnd - rayStart;  // math.normalize(rayEnd - rayStart);

                var rayInput           = new RaycastInput();
                rayInput.Ray.Origin    = rayStart;
                rayInput.Ray.Direction = rayDir;
                rayInput.Filter        = collider.Value.Value.Filter;

                Unity.Physics.RaycastHit rayHit;
                bool hit = (world.CastRay(rayInput, out rayHit) && rayHit.SurfaceNormal.y > 0.5);
                if (ccBodyComponentData.IsSupported && !hit)
                {
                    ccBodyComponentData.InitialUnsupportedVelocity = velocity.Linear;
                }
                ccBodyComponentData.IsSupported = hit;
            }

            // tweak velocity
            //this.MovementVector = new float3(1, 0, 0);
            //this.IsJumping = true;
            {
                float3 lv          = velocity.Linear;
                lv                *= ccBodyComponentData.MovementDamping;
                bool bHaveMovement = ccBodyComponentData.IsJumping || (math.lengthsq(ccBodyComponentData.MovementVector) > (ccBodyComponentData.DeadZone * ccBodyComponentData.DeadZone));
                if (bHaveMovement)
                {
                    float y = lv.y;
                    if (ccBodyComponentData.IsSupported)
                    {
                        lv   = ccBodyComponentData.MovementSpeed * ccBodyComponentData.MovementVector;
                        lv.y = y;
                        if (ccBodyComponentData.IsJumping)
                        {
                            lv.y += ccBodyComponentData.JumpSpeed;
                            ccBodyComponentData.IsJumping = false;
                        }
                    }
                    else
                    {
                        ccBodyComponentData.InitialUnsupportedVelocity  *= ccBodyComponentData.MovementDamping;
                        ccBodyComponentData.InitialUnsupportedVelocity.y = y;
                        lv = ccBodyComponentData.InitialUnsupportedVelocity + (ccBodyComponentData.MovementSpeed * ccBodyComponentData.MovementVector);
                    }
                }

                velocity.Linear  = lv;
                velocity.Angular = float3.zero;
            }
        });  // ForEach
Exemple #4
0
        public static bool RayCast <T>(ref T target, RaycastInput input, ref NativeList <RaycastHit> allHits) where T : struct, ICollidable
        {
            var collector = new AllHitsCollector <RaycastHit>(sfloat.One, ref allHits);

            return(target.CastRay(input, ref collector));
        }
Exemple #5
0
        private bool DetermineHoveredElements()
        {
            if (UIView.IsInsideUI() || !Cursor.visible)
            {
                return(false);
            }

            HoveredSegmentId = 0;
            HoveredNodeId    = 0;

            // find currently hovered node
            RaycastInput nodeInput = new RaycastInput(m_mouseRay, m_mouseRayLength)
            {
                m_netService =
                {
                    // find road segments
                    m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels,
                    m_service    = ItemClass.Service.Road
                },
                m_ignoreTerrain   = true,
                m_ignoreNodeFlags = NetNode.Flags.None
            };

            if (RayCast(nodeInput, out RaycastOutput nodeOutput))
            {
                HoveredNodeId = nodeOutput.m_netNode;
            }

            HoveredSegmentId = GetSegmentFromNode();

            if (HoveredSegmentId != 0)
            {
                Debug.Assert(HoveredNodeId != 0, "unexpected: HoveredNodeId == 0");
                return(true);
            }

            // find currently hovered segment
            var segmentInput = new RaycastInput(m_mouseRay, m_mouseRayLength)
            {
                m_netService =
                {
                    // find road segments
                    m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels,
                    m_service    = ItemClass.Service.Road
                },
                m_ignoreTerrain      = true,
                m_ignoreSegmentFlags = NetSegment.Flags.None
            };

            if (RayCast(segmentInput, out RaycastOutput segmentOutput))
            {
                HoveredSegmentId = segmentOutput.m_netSegment;
            }


            if (HoveredNodeId <= 0 && HoveredSegmentId > 0)
            {
                // alternative way to get a node hit: check distance to start and end nodes
                // of the segment
                ushort startNodeId = HoveredSegmentId.ToSegment().m_startNode;
                ushort endNodeId   = HoveredSegmentId.ToSegment().m_endNode;

                var vStart = segmentOutput.m_hitPos - startNodeId.ToNode().m_position;
                var vEnd   = segmentOutput.m_hitPos - endNodeId.ToNode().m_position;

                float startDist = vStart.magnitude;
                float endDist   = vEnd.magnitude;

                if (startDist < endDist && startDist < 75f)
                {
                    HoveredNodeId = startNodeId;
                }
                else if (endDist < startDist && endDist < 75f)
                {
                    HoveredNodeId = endNodeId;
                }
            }
            return(HoveredNodeId != 0 || HoveredSegmentId != 0);
        }
		private bool determineHoveredElements() {
			var mouseRayValid = !UIView.IsInsideUI() && Cursor.visible && !_cursorInSecondaryPanel;

			if (mouseRayValid) {
				ushort oldHoveredSegmentId = _hoveredSegmentIdx;
				ushort oldHoveredNodeId = _hoveredNetNodeIdx;

				_hoveredSegmentIdx = 0;
				_hoveredNetNodeIdx = 0;

				// find currently hovered node & segment

				/*var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
				var mouseRayLength = Camera.main.farClipPlane;
				var rayRight = Camera.main.transform.TransformDirection(Vector3.right);*/

				var nodeInput = new RaycastInput(this.m_mouseRay, this.m_mouseRayLength);
				//input.m_netService = new RaycastService(ItemClass.Service.Road, ItemClass.SubService.None, ItemClass.Layer.Default);
				//input.m_rayRight = rayRight;
				nodeInput.m_netService.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels;
				nodeInput.m_netService.m_service = ItemClass.Service.Road;
				nodeInput.m_netService2.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.PublicTransport | ItemClass.Layer.MetroTunnels;
				nodeInput.m_netService2.m_service = ItemClass.Service.PublicTransport;
				nodeInput.m_netService2.m_subService = ItemClass.SubService.PublicTransportTrain;
				nodeInput.m_ignoreTerrain = true;
				nodeInput.m_ignoreNodeFlags = NetNode.Flags.None;
				//nodeInput.m_ignoreSegmentFlags = NetSegment.Flags.Untouchable;

				RaycastOutput nodeOutput;
				if (RayCast(nodeInput, out nodeOutput)) {
					_hoveredNetNodeIdx = nodeOutput.m_netNode;
				}

				var segmentInput = new RaycastInput(this.m_mouseRay, this.m_mouseRayLength);
				//input.m_netService = new RaycastService(ItemClass.Service.Road, ItemClass.SubService.None, ItemClass.Layer.Default);
				//input.m_rayRight = rayRight;
				segmentInput.m_netService.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels;
				segmentInput.m_netService.m_service = ItemClass.Service.Road;
				segmentInput.m_netService2.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.PublicTransport | ItemClass.Layer.MetroTunnels;
				segmentInput.m_netService2.m_service = ItemClass.Service.PublicTransport;
				segmentInput.m_netService2.m_subService = ItemClass.SubService.PublicTransportTrain;
				segmentInput.m_ignoreTerrain = true;
				//nodeInput.m_ignoreNodeFlags = NetNode.Flags.None;
				segmentInput.m_ignoreSegmentFlags = NetSegment.Flags.Untouchable;

				RaycastOutput segmentOutput;
				if (RayCast(segmentInput, out segmentOutput)) {
					_hoveredSegmentIdx = segmentOutput.m_netSegment;

					if (_hoveredNetNodeIdx <= 0) {
						ushort startNodeId = Singleton<NetManager>.instance.m_segments.m_buffer[_hoveredSegmentIdx].m_startNode;
						ushort endNodeId = Singleton<NetManager>.instance.m_segments.m_buffer[_hoveredSegmentIdx].m_endNode;

						float startDist = (segmentOutput.m_hitPos - Singleton<NetManager>.instance.m_nodes.m_buffer[startNodeId].m_position).magnitude;
						float endDist = (segmentOutput.m_hitPos - Singleton<NetManager>.instance.m_nodes.m_buffer[endNodeId].m_position).magnitude;
						if (startDist < 10f)
							_hoveredNetNodeIdx = startNodeId;
						else if (endDist < 10f)
							_hoveredNetNodeIdx = endNodeId;
					}
				}

				if (oldHoveredNodeId != _hoveredNetNodeIdx || oldHoveredSegmentId != _hoveredSegmentIdx) {
					Log._Debug($"*** Mouse ray @ node {_hoveredNetNodeIdx}, segment {_hoveredSegmentIdx}, toolMode={_toolMode}");
                }

				return (_hoveredNetNodeIdx != 0 || _hoveredSegmentIdx != 0);
			} else {
				//Log.Message($"Mouse ray invalid: {UIView.IsInsideUI()} {Cursor.visible} {_cursorInSecondaryPanel}");
			}

			return mouseRayValid;
		}
Exemple #7
0
        private bool determineHoveredElements()
        {
            var mouseRayValid = !UIView.IsInsideUI() && Cursor.visible && (activeSubTool == null || !activeSubTool.IsCursorInPanel());

            if (mouseRayValid)
            {
                ushort oldHoveredSegmentId = HoveredSegmentId;
                ushort oldHoveredNodeId    = HoveredNodeId;

                HoveredSegmentId = 0;
                HoveredNodeId    = 0;

                // find currently hovered node
                var nodeInput = new RaycastInput(this.m_mouseRay, this.m_mouseRayLength);
                // find road nodes
                nodeInput.m_netService.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels;
                nodeInput.m_netService.m_service    = ItemClass.Service.Road;

                /*nodeInput.m_netService2.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.PublicTransport | ItemClass.Layer.MetroTunnels;
                 * nodeInput.m_netService2.m_service = ItemClass.Service.PublicTransport;
                 * nodeInput.m_netService2.m_subService = ItemClass.SubService.PublicTransportTrain;*/
                nodeInput.m_ignoreTerrain   = true;
                nodeInput.m_ignoreNodeFlags = NetNode.Flags.Untouchable;

                RaycastOutput nodeOutput;
                if (RayCast(nodeInput, out nodeOutput))
                {
                    HoveredNodeId = nodeOutput.m_netNode;
                }
                else
                {
                    // find train nodes
                    nodeInput.m_netService.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels;
                    nodeInput.m_netService.m_service    = ItemClass.Service.PublicTransport;
                    nodeInput.m_netService.m_subService = ItemClass.SubService.PublicTransportTrain;
                    nodeInput.m_ignoreTerrain           = true;
                    nodeInput.m_ignoreNodeFlags         = NetNode.Flags.Untouchable;

                    if (RayCast(nodeInput, out nodeOutput))
                    {
                        HoveredNodeId = nodeOutput.m_netNode;
                    }
                }

                // find currently hovered segment
                var segmentInput = new RaycastInput(this.m_mouseRay, this.m_mouseRayLength);
                // find road segments
                segmentInput.m_netService.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels;
                segmentInput.m_netService.m_service    = ItemClass.Service.Road;
                segmentInput.m_ignoreTerrain           = true;
                segmentInput.m_ignoreSegmentFlags      = NetSegment.Flags.Untouchable;

                RaycastOutput segmentOutput;
                if (RayCast(segmentInput, out segmentOutput))
                {
                    HoveredSegmentId = segmentOutput.m_netSegment;
                }
                else
                {
                    // find train segments
                    segmentInput.m_netService.m_itemLayers = ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels;
                    segmentInput.m_netService.m_service    = ItemClass.Service.PublicTransport;
                    segmentInput.m_netService.m_subService = ItemClass.SubService.PublicTransportTrain;
                    segmentInput.m_ignoreTerrain           = true;
                    segmentInput.m_ignoreSegmentFlags      = NetSegment.Flags.Untouchable;

                    if (RayCast(segmentInput, out segmentOutput))
                    {
                        HoveredSegmentId = segmentOutput.m_netSegment;
                    }
                }

                if (HoveredNodeId <= 0 && HoveredSegmentId > 0)
                {
                    // alternative way to get a node hit: check distance to start and end nodes of the segment
                    ushort startNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[HoveredSegmentId].m_startNode;
                    ushort endNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[HoveredSegmentId].m_endNode;

                    float startDist = (segmentOutput.m_hitPos - Singleton <NetManager> .instance.m_nodes.m_buffer[startNodeId].m_position).magnitude;
                    float endDist   = (segmentOutput.m_hitPos - Singleton <NetManager> .instance.m_nodes.m_buffer[endNodeId].m_position).magnitude;
                    if (startDist < endDist && startDist < 25f)
                    {
                        HoveredNodeId = startNodeId;
                    }
                    else if (endDist < startDist && endDist < 25f)
                    {
                        HoveredNodeId = endNodeId;
                    }
                }

                /*if (oldHoveredNodeId != HoveredNodeId || oldHoveredSegmentId != HoveredSegmentId) {
                 *      Log._Debug($"*** Mouse ray @ node {HoveredNodeId}, segment {HoveredSegmentId}, toolMode={GetToolMode()}");
                 * }*/

                return(HoveredNodeId != 0 || HoveredSegmentId != 0);
            }
            else
            {
                //Log._Debug($"Mouse ray invalid: {UIView.IsInsideUI()} {Cursor.visible} {activeSubTool == null} {activeSubTool.IsCursorInPanel()}");
            }

            return(mouseRayValid);
        }
		private bool determineHoveredElements() {
			var mouseRayValid = !UIView.IsInsideUI() && Cursor.visible && !_cursorInSecondaryPanel;

			if (mouseRayValid) {
				// find currently hovered node & segment
				
				var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
				var mouseRayLength = Camera.main.farClipPlane;
				var rayRight = Camera.main.transform.TransformDirection(Vector3.right);

				var input = new RaycastInput(mouseRay, mouseRayLength);
				input.m_netService = new RaycastService(ItemClass.Service.Road, ItemClass.SubService.None, ItemClass.Layer.Default);
				input.m_rayRight = rayRight;
				input.m_ignoreTerrain = true;
				input.m_ignoreNodeFlags = NetNode.Flags.None;
				input.m_ignoreSegmentFlags = NetSegment.Flags.Untouchable;

				RaycastOutput output;
				if (!RayCast(input, out output)) {
					_hoveredSegmentIdx = 0;
					_hoveredNetNodeIdx = 0;
					return false;
				}

				/*if (output.m_netNode != _hoveredNetNodeIdx || output.m_netSegment != _hoveredSegmentIdx) {
					Log.Message($"*** Mouse ray @ node {output.m_netNode}, segment {output.m_netSegment}, toolMode={_toolMode}");
                }*/

				_hoveredNetNodeIdx = output.m_netNode;
				_hoveredSegmentIdx = output.m_netSegment;
			} else {
				//Log.Message($"Mouse ray invalid: {UIView.IsInsideUI()} {Cursor.visible} {_cursorInSecondaryPanel}");
			}

			return mouseRayValid;
		}
Exemple #9
0
        private void HandleUserInput(CharacterControllerComponentData ccComponentData, float3 up, float3 surfaceVelocity, float3 position, quaternion rotation,
                                     ref CharacterControllerInternalData ccInternalData, ref float3 linearVelocity)
        {
            // Reset jumping state and unsupported velocity
            if (ccInternalData.SupportedState == CharacterSupportState.Supported)
            {
                ccInternalData.IsJumping           = false;
                ccInternalData.UnsupportedVelocity = float3.zero;
            }

            // Movement and jumping
            bool   shouldJump = false;
            float3 requestedMovementDirection = float3.zero;
            {
                float3 forward = math.forward(quaternion.identity);
                float3 right   = math.cross(up, forward);

                float horizontal    = ccInternalData.Input.Movement.x;
                float vertical      = ccInternalData.Input.Movement.y;
                bool  jumpRequested = ccInternalData.Input.Jumped > 0;
                bool  haveInput     = (math.abs(horizontal) > float.Epsilon) || (math.abs(vertical) > float.Epsilon);
                if (haveInput)
                {
                    float3 localSpaceMovement = forward * vertical + right * horizontal;
                    float3 worldSpaceMovement = math.rotate(quaternion.AxisAngle(up, ccInternalData.CurrentRotationAngle), localSpaceMovement);
                    requestedMovementDirection = math.normalize(worldSpaceMovement);
                }
                shouldJump = jumpRequested && ccInternalData.SupportedState == CharacterSupportState.Supported;
            }

            // Turning
            {
                var raycastInput = new RaycastInput
                {
                    Start  = cameraWorldPoint,
                    End    = cameraWorldPoint + new float3(0, -20f, 0f),
                    Filter = new CollisionFilter()
                    {
                        BelongsTo      = ~0u,
                        CollidesWith   = 1u << 5,
                            GroupIndex = 0
                    }
                };
                if (!PhysicsWorld.CastRay(raycastInput, out var hit))
                {
                    return;
                }

                var playerToMouse = hit.Position - position;
                playerToMouse.y = 0f;
                playerToMouse   = math.normalize(playerToMouse);

                var forward = math.mul(rotation, new float3(0, 0, 1));

                var angle = MathHelper.SignedAngle(forward, playerToMouse, new float3(0, 1, 0));

                var horizontal = math.clamp(math.remap(-180f, 180f, -ccComponentData.RotationSpeed, ccComponentData.RotationSpeed, angle), -1f, 1f);
                var haveInput  = (math.abs(horizontal) > 0.01f);
                if (haveInput)
                {
                    ccInternalData.CurrentRotationAngle += horizontal * ccComponentData.RotationSpeed * DeltaTime;
                }
            }

            // Apply input velocities
            {
                if (shouldJump)
                {
                    // Add jump speed to surface velocity and make character unsupported
                    ccInternalData.IsJumping           = true;
                    ccInternalData.SupportedState      = CharacterSupportState.Unsupported;
                    ccInternalData.UnsupportedVelocity = surfaceVelocity + ccComponentData.JumpUpwardsSpeed * up;
                }
                else if (ccInternalData.SupportedState != CharacterSupportState.Supported)
                {
                    // Apply gravity
                    ccInternalData.UnsupportedVelocity += ccComponentData.Gravity * DeltaTime;
                }
                // If unsupported then keep jump and surface momentum
                linearVelocity = requestedMovementDirection * ccComponentData.MovementSpeed +
                                 (ccInternalData.SupportedState != CharacterSupportState.Supported ? ccInternalData.UnsupportedVelocity : float3.zero);
            }
        }
Exemple #10
0
        protected override void OnToolUpdate()
        {
            base.OnToolUpdate();
            Ray          ray   = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastInput input = new RaycastInput(ray, Camera.main.farClipPlane);

            input.m_ignoreSegmentFlags       = NetSegment.Flags.None;
            input.m_ignoreNodeFlags          = NetNode.Flags.All;
            input.m_ignoreParkFlags          = DistrictPark.Flags.All;
            input.m_ignorePropFlags          = PropInstance.Flags.All;
            input.m_ignoreTreeFlags          = TreeInstance.Flags.All;
            input.m_ignoreCitizenFlags       = CitizenInstance.Flags.All;
            input.m_ignoreVehicleFlags       = Vehicle.Flags.Created;
            input.m_ignoreBuildingFlags      = Building.Flags.All;
            input.m_ignoreDisasterFlags      = DisasterData.Flags.All;
            input.m_ignoreTransportFlags     = TransportLine.Flags.All;
            input.m_ignoreParkedVehicleFlags = VehicleParked.Flags.All;
            input.m_ignoreTerrain            = true;
            RayCast(input, out RaycastOutput output);
            m_hover = output.m_netSegment;

            if (Input.GetKeyDown(KeyCode.Escape))
            {
                enabled = false;
                ToolsModifierControl.SetTool <DefaultTool>();
            }

            if (m_hover != 0)
            {
                m_netInfo = GetSegment(m_hover).Info;
                if (Input.GetMouseButtonUp(0))
                {
                    instance.enabled = false;
                    if (Singleton <UnlockManager> .instance.Unlocked(m_netInfo.m_UnlockMilestone))
                    {
                        // you know when you make a bugfix just to mess with people? well this is that bugfix. enjoy.
                        UIView.Find("E2A").Unfocus();

                        UIView.Find("TSCloseButton").SimulateClick();

                        enabled = false;

                        m_netTool = ToolsModifierControl.SetTool <NetTool>();

                        m_netInfo = FindDefaultElevation(m_netInfo);

                        // If we don't load UI, stuff happens, whatever.
                        List <UIComponent>        reveal = null;
                        ElektrixModsConfiguration config = Configuration <ElektrixModsConfiguration> .Load();

                        if (config.NP_OpenUI)
                        {
                            reveal = FindRoadInPanel(m_netInfo.name);
                        }

                        m_netTool.Prefab = m_netInfo;
                        if (reveal != null)
                        {
                            UIView.Find("TSCloseButton").SimulateClick();
                            Db.l("[Net Picker] Attempting to open panel " + reveal[1].parent.parent.parent.parent.name.Replace("Panel", ""));
                            UIButton rb = UIView.Find("MainToolstrip").Find <UIButton>(reveal[1].parent.parent.parent.parent.name.Replace("Panel", ""));
                            rb.SimulateClick();
                            reveal[0].SimulateClick();
                            reveal[1].SimulateClick();
                            if (!UIView.Find("TSCloseButton").isVisible)
                            {
                                Db.l("Failed");
                            }
                        }
                        else if (config.NP_OpenUI)
                        {
                            ThrowError("This net type is hidden and won't work properly if used by non-advanced users. In order to use this net, disable 'open ui' in Net Picker settings. If this net *isn't* actually hidden, please tweet your net type (and what menu it can be found in) to @cosigncosine. Thanks!");
                            ToolsModifierControl.SetTool <DefaultTool>();
                            UIView.Find("ElectricityPanel").Hide();
                        }
                        m_fakeNetTool = true;

                        //Debug.LogError(NetworkSkins.modPath);
                        ushort  segmentId = m_hover;
                        NetInfo prefab    = m_netInfo;

                        try
                        {
                            Type     segmentDataManagerType  = Type.GetType("NetworkSkins.Data.SegmentDataManager, NetworkSkins");
                            object   segmentDataManager      = segmentDataManagerType.GetField("Instance").GetValue(null);
                            object[] SegmentToSegmentDataMap = (object[])segmentDataManagerType.GetField("SegmentToSegmentDataMap").GetValue(segmentDataManager);

                            var segmentData = SegmentToSegmentDataMap[segmentId];
                            segmentDataManagerType.GetMethod("SetActiveOptions").Invoke(segmentDataManager, new object[] { prefab, segmentData });
                        }
                        catch (Exception e) { Debug.Log("Network skins isn't installed."); }

                        if (config.CloseWindow)
                        {
                            UIView.Find("ElektrixModsPanel").Hide();
                        }
                    }
                    else
                    {
                        ThrowError("This net type isn't unlocked yet! Wait until this unlock/milestone: " + m_netInfo.m_UnlockMilestone.m_name);
                    }
                }
            }
            else
            {
                m_netInfo = default(NetInfo);
            }
        }
        // simulation thread
        protected bool DetermineHoveredElements()
        {
            HoveredSegmentId = 0;
            HoveredNodeId    = 0;
            if (!m_mouseRayValid)
            {
                return(false);
            }

            // find currently hovered node
            RaycastInput nodeInput = new RaycastInput(m_mouseRay, m_mouseRayLength)
            {
                m_netService      = GetService(),
                m_ignoreTerrain   = true,
                m_ignoreNodeFlags = NetNode.Flags.None,
            };

            if (RayCast(nodeInput, out raycastOutput))
            {
                HoveredNodeId = raycastOutput.m_netNode;
            }

            HoveredSegmentId = GetSegmentFromNode(raycastOutput.m_hitPos);

            if (HoveredSegmentId != 0)
            {
                Debug.Assert(HoveredNodeId != 0, "unexpected: HoveredNodeId == 0");
                return(true);
            }

            // find currently hovered segment
            var segmentInput = new RaycastInput(m_mouseRay, m_mouseRayLength)
            {
                m_netService         = GetService(),
                m_ignoreTerrain      = true,
                m_ignoreSegmentFlags = NetSegment.Flags.None
            };

            if (RayCast(segmentInput, out raycastOutput))
            {
                HoveredSegmentId = raycastOutput.m_netSegment;
            }

            if (HoveredNodeId <= 0 && HoveredSegmentId > 0)
            {
                // alternative way to get a node hit: check distance to start and end nodes
                // of the segment
                ushort startNodeId = HoveredSegmentId.ToSegment().m_startNode;
                ushort endNodeId   = HoveredSegmentId.ToSegment().m_endNode;

                var vStart = raycastOutput.m_hitPos - startNodeId.ToNode().m_position;
                var vEnd   = raycastOutput.m_hitPos - endNodeId.ToNode().m_position;

                float startDist = vStart.magnitude;
                float endDist   = vEnd.magnitude;

                if (startDist < endDist && startDist < 75f)
                {
                    HoveredNodeId = startNodeId;
                }
                else if (endDist < startDist && endDist < 75f)
                {
                    HoveredNodeId = endNodeId;
                }
            }
            return(HoveredNodeId != 0 || HoveredSegmentId != 0);
        }
Exemple #12
0
    protected override void OnUpdate()
    {
        CollisionFilter collisionFilter = new CollisionFilter()
        {
            BelongsTo    = ~0u,
            CollidesWith = ~0u, // all 1s, so all layers, collide with everything
            GroupIndex   = 0
        };
        EntityManager  entityManager  = World.EntityManager;
        CollisionWorld collisionWorld = physicsWorld.PhysicsWorld.CollisionWorld;

        Dependency = Entities.WithAll <AnimalTag>().ForEach((ref AnimalMovementData mvmtData, in Translation translation) => {
            float3 start = new float3(translation.Value.x, translation.Value.y, translation.Value.z + 0.2f);

            #region front
            RaycastInput inputFront = new RaycastInput()
            {
                Start  = start,
                End    = new float3(translation.Value.x, translation.Value.y, translation.Value.z + (2.5f * mvmtData.movementSpeed)),
                Filter = collisionFilter
            };
            RaycastHit hitFront = new RaycastHit();
            bool hasHitFront    = collisionWorld.CastRay(inputFront, out hitFront);
            #endregion
            #region front right
            RaycastInput inputFR = new RaycastInput()
            {
                Start  = start,
                End    = new float3(translation.Value.x + (2.5f * mvmtData.movementSpeed), translation.Value.y, translation.Value.z + (2.5f * mvmtData.movementSpeed)),
                Filter = collisionFilter
            };
            RaycastHit hitFR = new RaycastHit();
            bool hasHitFR    = collisionWorld.CastRay(inputFR, out hitFR);
            #endregion
            #region front left
            RaycastInput inputFL = new RaycastInput()
            {
                Start  = start,
                End    = new float3(translation.Value.x - (2.5f * mvmtData.movementSpeed), translation.Value.y, translation.Value.z + (2.5f * mvmtData.movementSpeed)),
                Filter = collisionFilter
            };
            RaycastHit hitFL = new RaycastHit();
            bool hasHitFL    = collisionWorld.CastRay(inputFR, out hitFL);
            #endregion

            if (hasHitFront)
            {
                float3 normal = hitFront.SurfaceNormal;
                //AnimalMovementData mvmtDataHitEntity = entityManager.GetComponentData<AnimalMovementData>(hitEntity);
                //float maxSpeed = math.max(mvmtData.movementSpeed, mvmtDataHitEntity.movementSpeed);

                float dotProduct = math.dot(math.normalize(mvmtData.targetDirection - translation.Value), math.normalize(hitFront.SurfaceNormal));

                float angle = 0.262f;
                angle      += 1f - math.abs(dotProduct);
                //angle += (1f - (maxSpeed * 0.1f));
                angle = math.clamp(angle, 0f, StaticValues.AVOIDANCE_MIN_ANGLE);
                quaternion newRotation = quaternion.RotateY(angle);
                float3 newDirection    = math.rotate(newRotation, mvmtData.direction);
                newDirection           = math.normalizesafe(newDirection);
                // Set EntityA's target direction
                mvmtData.targetDirection = newDirection;
            }
            else if (hasHitFR)
            {
                float3 normal = hitFR.SurfaceNormal;
                //AnimalMovementData mvmtDataHitEntity = entityManager.GetComponentData<AnimalMovementData>(hitEntity);
                //float maxSpeed = math.max(mvmtData.movementSpeed, mvmtDataHitEntity.movementSpeed);

                float dotProduct = math.dot(math.normalize(mvmtData.targetDirection - translation.Value), math.normalize(hitFR.SurfaceNormal));

                float angle = 0.262f;
                angle      += 1f - math.abs(dotProduct);
                //angle += (1f - (maxSpeed * 0.1f));
                angle = math.clamp(angle, 0f, StaticValues.AVOIDANCE_MIN_ANGLE);
                quaternion newRotation = quaternion.RotateY(angle);
                float3 newDirection    = math.rotate(newRotation, mvmtData.direction);
                newDirection           = math.normalizesafe(newDirection);
                // Set EntityA's target direction
                mvmtData.targetDirection = newDirection;
            }
            else if (hasHitFL)
            {
                float3 normal = hitFR.SurfaceNormal;
                //AnimalMovementData mvmtDataHitEntity = entityManager.GetComponentData<AnimalMovementData>(hitEntity);
                //float maxSpeed = math.max(mvmtData.movementSpeed, mvmtDataHitEntity.movementSpeed);

                float dotProduct = math.dot(math.normalize(mvmtData.targetDirection - translation.Value), math.normalize(hitFR.SurfaceNormal));

                float angle = 0.262f;
                angle      += 1f - math.abs(dotProduct);
                //angle += (1f - (maxSpeed * 0.1f));
                angle = math.clamp(angle, 0f, StaticValues.AVOIDANCE_MIN_ANGLE);
                quaternion newRotation = quaternion.RotateY(angle);
                float3 newDirection    = math.rotate(newRotation, mvmtData.direction);
                newDirection           = math.normalizesafe(newDirection);
                // Set EntityA's target direction
                mvmtData.targetDirection = newDirection;
            }
        }).Schedule(Dependency);

        Dependency.Complete();
    }
        protected override void OnUpdate()
        {
            var     collisionWorld = m_BuildPhysicsWorld.PhysicsWorld.CollisionWorld;
            Vector2 mousePosition  = Input.mousePosition;

            UnityEngine.Ray unityRay = Camera.main.ScreenPointToRay(mousePosition);
            var             rayInput = new RaycastInput
            {
                Start  = unityRay.origin,
                End    = unityRay.origin + unityRay.direction * MousePickSystem.k_MaxDistance,
                Filter = CollisionFilter.Default,
            };

            var mouseHoverEntity = GetSingletonEntity <MouseHover>();
            var mouseHover       = EntityManager.GetSharedComponentData <MouseHover>(mouseHoverEntity);

            RaycastHit hit;

            using (var raycastHitRef = new NativeReference <RaycastHit>(Allocator.TempJob))
            {
                var rcj = new WorldRaycastJob()
                {
                    CollisionWorld = collisionWorld,
                    RayInput       = rayInput,
                    IgnoreTriggers = mouseHover.IgnoreTriggers,
                    IgnoreStatic   = mouseHover.IgnoreStatic,
                    RaycastHitRef  = raycastHitRef
                };
                rcj.Run();
                hit = raycastHitRef.Value;
            }

            var graphicsEntity = FindGraphicsEntityFromPhysics(hit.Entity, hit.ColliderKey);

            // If still hovering over the same entity then do nothing.
            if (mouseHover.CurrentEntity.Equals(graphicsEntity))
            {
                return;
            }

            mouseHover.PreviousEntity = mouseHover.CurrentEntity;
            mouseHover.CurrentEntity  = graphicsEntity;

            bool hasPreviousEntity = !mouseHover.PreviousEntity.Equals(Entity.Null);
            bool hasCurrentEntity  = !mouseHover.CurrentEntity.Equals(Entity.Null);

            // If there was a previous entity and it had a RenderMesh then reset its Material
            if (hasPreviousEntity && EntityManager.HasComponent <RenderMesh>(mouseHover.PreviousEntity))
            {
                var renderMesh = EntityManager.GetSharedComponentData <RenderMesh>(mouseHover.PreviousEntity);
                renderMesh.material = mouseHover.OriginalMaterial;
                EntityManager.SetSharedComponentData(mouseHover.PreviousEntity, renderMesh);
            }

            // If there was a new current entity and it has a RenderMesh then set its Material
            if (hasCurrentEntity && EntityManager.HasComponent <RenderMesh>(mouseHover.CurrentEntity))
            {
                var renderMesh = EntityManager.GetSharedComponentData <RenderMesh>(mouseHover.CurrentEntity);
                mouseHover.OriginalMaterial = renderMesh.material;
                mouseHover.PreviousEntity   = mouseHover.CurrentEntity;
                mouseHover.CurrentEntity    = graphicsEntity;
                renderMesh.material         = mouseHover.HoverMaterial;
                EntityManager.SetSharedComponentData(mouseHover.CurrentEntity, renderMesh);
            }

            EntityManager.SetSharedComponentData(mouseHoverEntity, mouseHover);
        }
        public static bool RayCastSegmentAndNode(out RaycastOutput output)
        {
            RaycastInput input = new RaycastInput(Camera.main.ScreenPointToRay(Input.mousePosition), Camera.main.farClipPlane);
            input.m_netService.m_service = ItemClass.Service.Road;
            input.m_netService.m_itemLayers = ItemClass.Layer.Default;
            input.m_ignoreSegmentFlags = NetSegment.Flags.None;
            input.m_ignoreNodeFlags = NetNode.Flags.None;
            input.m_ignoreTerrain = true;

            return RayCast(input, out output);
        }
Exemple #15
0
 public bool CastRay(RaycastInput input) => QueryWrappers.RayCast(ref this, input);
Exemple #16
0
 public bool CastRay(RaycastInput input, ref NativeList <RaycastHit> allHits) => QueryWrappers.RayCast(ref this, input, ref allHits);
Exemple #17
0
 public bool CastRay <T>(RaycastInput input, ref T collector) where T : struct, ICollector <RaycastHit>
 {
     return(Collider != null && Collider->CastRay(input, ref collector));
 }
Exemple #18
0
 public bool DoRayCast(RaycastInput input, out RaycastOutput output)
 {
     return(RayCast(input, out output));
 }
Exemple #19
0
    protected override void OnUpdate()
    {
        _physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem <BuildPhysicsWorld>();
        _world = _physicsWorldSystem.PhysicsWorld.CollisionWorld;

        if (Input.GetMouseButtonDown(1) && !_isDragging)
        {
            Unity.Physics.RaycastHit hit = SingleRaycast();
            if (hit.Entity != Entity.Null)
            {
                // TODO this single raycast needs to hit a VALID terrain piece
                ShowAllDragIndicators();
                _dragStartPos = hit.Position;
                _isDragging   = true;
            }
            else
            {
                HideAllDragIndicators();
                _isDragging = false;
            }
        }
        else if (_isDragging && Input.GetMouseButton(1))
        {
            Unity.Physics.RaycastHit hit = SingleRaycast();
            float3 dragEndPos            = hit.Position;

            // Ignore dragging if some distance threshold is not met
            // Or if there are no selected formations
            if (hit.Entity == Entity.Null || math.distancesq(_dragStartPos, dragEndPos) < 5f)
            {
                isValidDrag = false;
                return;
            }

            // Check if its a valid drag for the # of selected formations
            var selectedFormations = GetSelectedFormations();
            if (!selectedFormations.IsCreated || selectedFormations.Length == 0)
            {
                Debug.Log("No formations selected");
                return;
            }

            var   numSelectedFormations = selectedFormations.Length;
            float dragDist = math.distance(_dragStartPos, dragEndPos);

            // TODO formation width may NOT be evenly split
            float formationWidth = dragDist / numSelectedFormations; // Width for each formation (evenly split)
            if (formationWidth < MIN_FORMATION_WIDTH)
            {
                return;
            }

            // Red line to show the width of drag
            //Debug.DrawLine(dragStartPos, dragEndPos, Color.red, 0f, true);

            // Preparing batch raycasts in between the two drag positions to get curvature of the terrain
            // TODO this can be jobified, right?
            float3     dragDir   = math.normalize(dragEndPos - _dragStartPos);
            quaternion rotateFor = quaternion.AxisAngle(new float3(0f, 1f, 0f), math.radians(-90f));
            float3     dragFor   = math.mul(rotateFor, dragDir);
            _dragForward = dragFor;

            var numSelectedUnits = _selectedFormationUnitQuery.CalculateEntityCount();
            if (!TEMP_SLOT_ASSIGNMENTS.IsCreated)
            {
                TEMP_SLOT_ASSIGNMENTS = new NativeArray <float3>(numSelectedUnits, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            }
            else if (TEMP_SLOT_ASSIGNMENTS.Length != numSelectedUnits)
            {
                // Very common case to have to resize
                TEMP_SLOT_ASSIGNMENTS.Dispose();
                TEMP_SLOT_ASSIGNMENTS = new NativeArray <float3>(numSelectedUnits, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            }

            var raycastInputs        = new NativeArray <RaycastInput>(numSelectedUnits, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            var formationUnitIndices = new NativeArray <int>(numSelectedFormations, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            // TODO Calculate centroid of each formation. Assign formations accordingly.

            var currUnitIndex = 0;
            for (int i = 0; i < selectedFormations.Length; i++)
            {
                var currFormation = selectedFormations[i];

                // Filters to an existing query to calculate unit count for one formation
                _selectedUnitQuery.SetSharedComponentFilter(currFormation);
                int numUnits = _selectedUnitQuery.CalculateEntityCount();

                var raycastInputsSlice = raycastInputs.Slice(currUnitIndex, numUnits);

                numUnitsPerRow = math.clamp((int)(formationWidth / _distanceApart), MIN_FORMATION_WIDTH, MAX_FORMATION_WIDTH);

                // Draws the forward direction of the formation in white
                //Debug.DrawRay(math.lerp(dragStartPos, dragEndPos, 0.5f), dragFor);

                float3 startPoint = math.lerp(_dragStartPos, dragEndPos, (float)i / selectedFormations.Length);

                // TODO not working
                CollisionFilter raycastFilter = new CollisionFilter()
                {
                    BelongsTo    = _walkableLayer,
                    CollidesWith = _walkableLayer,
                    GroupIndex   = 0
                };


                #region Creating raycast inputs
                int    levels = numUnits / numUnitsPerRow;
                float3 forwardOffset;
                for (int currLevel = 0; currLevel < levels; currLevel++)
                {
                    forwardOffset = dragFor * currLevel * _distanceApart;
                    for (int j = 0; j < numUnitsPerRow; j++)
                    {
                        float3 sideOffset  = dragDir * _distanceApart * j;
                        float3 currUnitPos = startPoint + sideOffset - forwardOffset;
                        raycastInputsSlice[j + (numUnitsPerRow * currLevel)] = new RaycastInput {
                            Start  = currUnitPos + new float3(0f, 20f, 0f),
                            End    = currUnitPos - new float3(0f, 20f, 0f),
                            Filter = raycastFilter
                        };
                        // DEBUG
                        //Debug.DrawLine(currUnitPos, currUnitPos + new float3(0f, 1f, 0f), Color.blue);
                    }
                }
                // For the remainder units in the back
                int    calculatedUnits = numUnitsPerRow * levels; // The number of units we have finished calculating
                int    remainderUnits  = numUnits % numUnitsPerRow;
                float3 middlePos       = (startPoint + (dragDir * numUnitsPerRow / 2 * _distanceApart)) - (dragDir * _distanceApart * remainderUnits / 2);
                forwardOffset = dragFor * levels * _distanceApart;
                for (int j = 0; j < remainderUnits; j++)
                {
                    float3 sideOffset  = dragDir * _distanceApart * j;
                    float3 currUnitPos = middlePos + sideOffset - forwardOffset;
                    raycastInputsSlice[calculatedUnits + j] = new RaycastInput {
                        Start  = currUnitPos + new float3(0f, 5f, 0f),
                        End    = currUnitPos - new float3(0f, 5f, 0f),
                        Filter = raycastFilter
                    };

                    // DEBUG
                    //Debug.DrawLine(currUnitPos, currUnitPos + new float3(0f, 1f, 0f), Color.green);
                }

                formationUnitIndices[i] = currUnitIndex;
                currUnitIndex          += numUnits;

                #endregion
            }

            NativeArray <float3> raycastResults = new NativeArray <float3>(numSelectedUnits, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
            // Runs the batch of raycasts
            // TODO schedule these raycasts all at once. This is very slow
            var handle = RaycastUtils.ScheduleBatchRayCastPosition(_world, raycastInputs, raycastResults, Dependency, out var hasFailed);
            handle.Complete();
            raycastInputs.Dispose();

            if (hasFailed)
            {
                Debug.Log("Dragging failed, disposing raycast results");
                raycastResults.Dispose();
                return;
            }

            ShowSelectedDragIndicators();

            var handles = new NativeArray <JobHandle>(selectedFormations.Length, Allocator.TempJob);

            var translations = GetComponentDataFromEntity <Translation>(false);
            var rotations    = GetComponentDataFromEntity <Rotation>(false);
            for (int i = 0; i < selectedFormations.Length; i++)
            {
                var currFormation      = selectedFormations[i];
                var unitPositionsSlice = raycastResults.Slice(formationUnitIndices[i]);

                handles[i] = Entities
                             .WithName("AlignUnitDragIndicators")
                             .WithReadOnly(unitPositionsSlice)
                             .WithAll <DragIndicatorTag, Translation, Rotation>()
                             .WithSharedComponentFilter(currFormation)
                             .WithNativeDisableContainerSafetyRestriction(translations)
                             .WithNativeDisableContainerSafetyRestriction(rotations)
                             .ForEach((Entity entity, int entityInQueryIndex) =>
                {
                    translations[entity] = new Translation
                    {
                        Value = unitPositionsSlice[entityInQueryIndex] + new float3(0f, 0.1f, 0f)
                    };
                    rotations[entity] = new Rotation {
                        Value = quaternion.LookRotation(dragFor, math.up())
                    };
                }).ScheduleParallel(Dependency);
            }

            new CopyFloat3Job
            {
                Output = TEMP_SLOT_ASSIGNMENTS,
                Input  = raycastResults
            }.Schedule(raycastResults.Length, 128, JobHandle.CombineDependencies(handles)).Complete();

            isValidDrag = true;
            handles.Dispose();
            formationUnitIndices.Dispose();
        }
        else if (isValidDrag && Input.GetMouseButtonUp(1))
        {
            isValidDrag = false;

            EaseOfAssignmentUnitAssignment();
            //SpatialUnitAssignmnet();
        }
        else
        {
            _isDragging = false;
            if (Input.GetKey(KeyCode.Space))
            {
                ShowAllDragIndicators();
            }
            else
            {
                HideAllDragIndicators();
            }
        }

        _endSimulationEcbSystem.AddJobHandleForProducer(this.Dependency);
    }
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            var commandBuffer          = barrier.CreateCommandBuffer().ToConcurrent();
            var elapsedSeconds         = (float)Time.ElapsedTime;
            var deltaSeconds           = Time.DeltaTime;
            var physicsWorld           = buildPhysicsWorld.PhysicsWorld;
            var pathBufferFromEntity   = GetBufferFromEntity <NavPathBufferElement>(true);
            var localToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true);

            var walkJob = Entities
                          .WithNone <NavPlanning, NavJumping>()
                          .WithAll <NavLerping, LocalToParent>()
                          .WithReadOnly(pathBufferFromEntity)
                          .WithReadOnly(localToWorldFromEntity)
                          .WithReadOnly(physicsWorld)
                          .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, ref Translation translation, ref Rotation rotation, in Parent surface) =>
            {
                var pathBuffer = pathBufferFromEntity[entity];

                if (pathBuffer.Length == 0)
                {
                    return;
                }

                if (agent.PathBufferIndex >= pathBuffer.Length)
                {
                    --agent.PathBufferIndex;
                    return;
                }

                var localDestination = agent.LocalDestination;

                var localWaypoint = pathBuffer[agent.PathBufferIndex].Value;
                localWaypoint.y   = agent.Offset.y;

                if (
                    NavUtil.ApproxEquals(translation.Value, localWaypoint, 1) &&
                    ++agent.PathBufferIndex > pathBuffer.Length - 1
                    )
                {
                    var rayInput = new RaycastInput
                    {
                        Start  = localToWorldFromEntity[entity].Position + agent.Offset,
                        End    = math.forward(rotation.Value) * NavConstants.OBSTACLE_RAYCAST_DISTANCE_MAX,
                        Filter = new CollisionFilter
                        {
                            BelongsTo    = NavUtil.ToBitMask(NavConstants.COLLIDER_LAYER),
                            CollidesWith = NavUtil.ToBitMask(NavConstants.OBSTACLE_LAYER)
                        }
                    };

                    if (
                        !surface.Value.Equals(agent.DestinationSurface) &&
                        !NavUtil.ApproxEquals(translation.Value, localDestination, 1) &&
                        !physicsWorld.CastRay(rayInput, out RaycastHit hit)
                        )
                    {
                        agent.JumpSeconds = elapsedSeconds;
                        commandBuffer.AddComponent <NavJumping>(entityInQueryIndex, entity);
                        commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity);
                        return;
                    }

                    commandBuffer.RemoveComponent <NavLerping>(entityInQueryIndex, entity);
                    commandBuffer.RemoveComponent <NavNeedsDestination>(entityInQueryIndex, entity);
                    agent.PathBufferIndex = 0;
                    return;
                }

                var lookAt     = localDestination;
                lookAt.y       = translation.Value.y;
                rotation.Value = quaternion.LookRotationSafe(lookAt - translation.Value, math.up());

                translation.Value = Vector3.MoveTowards(translation.Value, localWaypoint, agent.TranslationSpeed * deltaSeconds);
            })
                          .WithName("NavWalkJob")
                          .Schedule(
                JobHandle.CombineDependencies(
                    inputDeps,
                    buildPhysicsWorld.FinalJobHandle
                    )
                );

            barrier.AddJobHandleForProducer(walkJob);

            var jumpBufferFromEntity = GetBufferFromEntity <NavJumpBufferElement>();
            var fallingFromEntity    = GetComponentDataFromEntity <NavFalling>();

            var artificialGravityJob = Entities
                                       .WithAny <NavFalling, NavJumping>()
                                       .WithAll <LocalToParent>()
                                       .WithReadOnly(fallingFromEntity)
                                       .WithReadOnly(jumpBufferFromEntity)
                                       .WithReadOnly(localToWorldFromEntity)
                                       .ForEach((Entity entity, int entityInQueryIndex, ref Translation translation, in NavAgent agent, in Parent surface) =>
            {
                commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity);

                var jumpBuffer = jumpBufferFromEntity[entity];

                if (jumpBuffer.Length == 0 && !fallingFromEntity.Exists(entity))
                {
                    return;
                }

                var destination = NavUtil.MultiplyPoint3x4(
                    localToWorldFromEntity[agent.DestinationSurface].Value,
                    agent.LocalDestination
                    );

                var velocity  = Vector3.Distance(translation.Value, destination) / (math.sin(2 * math.radians(agent.JumpDegrees)) / agent.JumpGravity);
                var yVelocity = math.sqrt(velocity) * math.sin(math.radians(agent.JumpDegrees));
                var waypoint  = translation.Value + math.up() * float.NegativeInfinity;

                if (!fallingFromEntity.Exists(entity))
                {
                    var xVelocity = math.sqrt(velocity) * math.cos(math.radians(agent.JumpDegrees)) * agent.JumpSpeedMultiplierX;

                    waypoint = NavUtil.MultiplyPoint3x4(     // To world (from local in terms of destination surface).
                        localToWorldFromEntity[agent.DestinationSurface].Value,
                        jumpBuffer[0].Value
                        );

                    waypoint = NavUtil.MultiplyPoint3x4(     // To local (in terms of agent's current surface).
                        math.inverse(localToWorldFromEntity[surface.Value].Value),
                        waypoint
                        );

                    translation.Value = Vector3.MoveTowards(translation.Value, waypoint, xVelocity * deltaSeconds);
                }

                translation.Value.y += (yVelocity - (elapsedSeconds - agent.JumpSeconds) * agent.JumpGravity) * deltaSeconds * agent.JumpSpeedMultiplierY;

                if (elapsedSeconds - agent.JumpSeconds >= NavConstants.JUMP_SECONDS_MAX)
                {
                    commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity);
                    commandBuffer.AddComponent <NavFalling>(entityInQueryIndex, entity);
                }

                if (!NavUtil.ApproxEquals(translation.Value, waypoint, 1))
                {
                    return;
                }

                commandBuffer.AddComponent <NavNeedsSurface>(entityInQueryIndex, entity);
                commandBuffer.RemoveComponent <NavJumping>(entityInQueryIndex, entity);
            })
    protected override void OnUpdate()
    {
        var commandBuffer = new EntityCommandBuffer(Allocator.TempJob);

        Entities
        .WithName("InitializeCameraOldPositionsJob")
        .WithBurst()
        .WithNone <Initialized>()
        .ForEach((Entity entity, ref CameraSmoothTrackSettings cameraSmoothTrack, in LocalToWorld localToWorld) =>
        {
            commandBuffer.AddComponent <Initialized>(entity);
            cameraSmoothTrack.OldPositionTo = HasComponent <LocalToWorld>(cameraSmoothTrack.LookTo)
                    ? GetComponent <LocalToWorld>(cameraSmoothTrack.LookTo).Position
                    : localToWorld.Position + new float3(0f, 0f, 1f);
        }).Run();
        commandBuffer.Playback(EntityManager);
        commandBuffer.Dispose();

        PhysicsWorld world = m_BuildPhysicsWorld.PhysicsWorld;

        var timestep  = (float)m_RecordMostRecentFixedTime.MostRecentDeltaTime;
        var timeAhead = Time.DeltaTime / timestep;

        Entities
        .WithName("SmoothlyTrackCameraTargetsJob")
        .WithoutBurst()
        .WithAll <Initialized>()
        .WithReadOnly(world)
        .ForEach((CameraSmoothTrack monoBehaviour, ref CameraSmoothTrackSettings cameraSmoothTrack, in LocalToWorld localToWorld) =>
        {
            var worldPosition = (float3)monoBehaviour.transform.position;

            float3 newPositionFrom = HasComponent <LocalToWorld>(cameraSmoothTrack.LookFrom)
                    ? GetComponent <LocalToWorld>(cameraSmoothTrack.LookFrom).Position
                    : worldPosition;

            float3 newPositionTo = HasComponent <LocalToWorld>(cameraSmoothTrack.LookTo)
                    ? GetComponent <LocalToWorld>(cameraSmoothTrack.LookTo).Position
                    : worldPosition + localToWorld.Forward;

            // check barrier
            var rayInput = new RaycastInput
            {
                Start  = newPositionFrom,
                End    = newPositionTo,
                Filter = CollisionFilter.Default
            };

            if (world.CastRay(rayInput, out RaycastHit rayResult))
            {
                newPositionFrom = rayResult.Position;
            }

            if (cameraSmoothTrack.Target != Entity.Null)
            {
                // add velocity
                float3 lv        = world.GetLinearVelocity(world.GetRigidBodyIndex(cameraSmoothTrack.Target));
                lv              *= timeAhead;
                newPositionFrom += lv;
                newPositionTo   += lv;
            }

            newPositionFrom = math.lerp(worldPosition, newPositionFrom, cameraSmoothTrack.LookFromInterpolateFactor);
            newPositionTo   = math.lerp(cameraSmoothTrack.OldPositionTo, newPositionTo, cameraSmoothTrack.LookToInteroplateFactor);

            float3 newForward      = newPositionTo - newPositionFrom;
            newForward             = math.normalizesafe(newForward);
            quaternion newRotation = quaternion.LookRotation(newForward, math.up());

            monoBehaviour.transform.SetPositionAndRotation(newPositionFrom, newRotation);
            cameraSmoothTrack.OldPositionTo = newPositionTo;
        }).Run();
    }
Exemple #22
0
        protected override void OnUpdate()
        {
            var enemyCount  = m_EnemyQuery.CalculateEntityCount();
            var targetCount = m_TargetQuery.CalculateEntityCount();

            EntityManager.GetAllUniqueSharedComponentData(m_UniqueTypes);

            // Each variant of the Boid represents a different value of the SharedComponentData and is self-contained,
            // meaning Boids of the same variant only interact with one another. Thus, this loop processes each
            // variant type individually.
            for (int boidVariantIndex = 0; boidVariantIndex < m_UniqueTypes.Count; boidVariantIndex++)
            {
                var settings = m_UniqueTypes[boidVariantIndex];
                m_BoidQuery.AddSharedComponentFilter(settings);

                var boidCount = m_BoidQuery.CalculateEntityCount();

                if (boidCount == 0)
                {
                    // Early out. If the given variant includes no Boids, move on to the next loop.
                    // For example, variant 0 will always exit early bc it's it represents a default, uninitialized
                    // Boid struct, which does not appear in this sample.
                    m_BoidQuery.ResetFilter();
                    continue;
                }

                // The following calculates spatial cells of neighboring Boids
                // note: working with a sparse grid and not a dense bounded grid so there
                // are no predefined borders of the space.

                var hashMap                 = new NativeMultiHashMap <int, int>(boidCount, Allocator.TempJob);
                var cellIndices             = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellEnemyPositionIndex  = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellTargetPositionIndex = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellCount               = new NativeArray <int>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellEnemyDistance       = new NativeArray <float>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellAlignment           = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var cellSeparation          = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var raycastInputs           = new NativeArray <RaycastInput>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var initialRaycastResults   = new NativeArray <RaycastHit>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var unobstructedDirections  = new NativeArray <float3>(boidCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var copyTargetPositions     = new NativeArray <float3>(targetCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                var copyEnemyPositions      = new NativeArray <float3>(enemyCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                // The following jobs all run in parallel because the same JobHandle is passed for their
                // input dependencies when the jobs are scheduled; thus, they can run in any order (or concurrently).
                // The concurrency is property of how they're scheduled, not of the job structs themselves.

                // These jobs extract the relevant position, heading component
                // to NativeArrays so that they can be randomly accessed by the `MergeCells` and `Steer` jobs.
                // These jobs are defined inline using the Entities.ForEach lambda syntax.
                var initialCellAlignmentJobHandle = Entities
                                                    .WithSharedComponentFilter(settings)
                                                    .WithName("InitialCellAlignmentJob")
                                                    .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    cellAlignment[entityInQueryIndex] = localToWorld.Forward;
                })
                                                    .ScheduleParallel(Dependency);

                var initialCellSeparationJobHandle = Entities
                                                     .WithSharedComponentFilter(settings)
                                                     .WithName("InitialCellSeparationJob")
                                                     .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    cellSeparation[entityInQueryIndex] = localToWorld.Position;
                })
                                                     .ScheduleParallel(Dependency);

                var initialRaycastInputsJobHandle = Entities
                                                    .WithSharedComponentFilter(settings)
                                                    .WithName("InitialRaycastInputsJob")
                                                    .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld) =>
                {
                    raycastInputs[entityInQueryIndex] = new RaycastInput
                    {
                        Start  = localToWorld.Position,
                        End    = localToWorld.Position + (localToWorld.Forward * settings.OuterDetectionRadius),
                        Filter = new CollisionFilter
                        {
                            BelongsTo    = ~0u,
                            CollidesWith = 1,     // Environment layer
                            GroupIndex   = 0
                        },
                    };
                })
                                                    .ScheduleParallel(Dependency);

                var world = World.DefaultGameObjectInjectionWorld.GetExistingSystem <Unity.Physics.Systems.BuildPhysicsWorld>().PhysicsWorld.CollisionWorld;
                var batchRaycastJobHandle = ScheduleBatchRayCast(world, raycastInputs, initialRaycastResults, initialRaycastInputsJobHandle);

                var findUnobstructedDirectionsJobHandle = Entities
                                                          .WithName("FindUnobstructedDirectionsJob")
                                                          .WithSharedComponentFilter(settings)
                                                          .ForEach((int entityInQueryIndex, in LocalToWorld localToWorld, in DynamicBuffer <Float3BufferElement> buffer) =>
                {
                    JobLogger.Log("In find unobstructed job");
                    float3 bestDir    = float3.zero;
                    float furthestHit = 0f;
                    RaycastHit hit;
                    DynamicBuffer <float3> float3buffer = buffer.Reinterpret <float3>();
                    for (int i = 0; i < float3buffer.Length; i++)
                    {
                        float3 end         = localToWorld.Position + ((math.mul(localToWorld.Value, new float4(float3buffer[i], 1)) * settings.OuterDetectionRadius)).xyz;
                        RaycastInput input = new RaycastInput()
                        {
                            Start  = localToWorld.Position,
                            End    = end,
                            Filter = new CollisionFilter
                            {
                                BelongsTo    = ~0u,
                                CollidesWith = 1,     // Environment layer
                                GroupIndex   = 0
                            },
                        };
                        if (world.CastRay(input, out hit))
                        {
                            var dist = math.distance(hit.Position, localToWorld.Position);
                            if (dist > furthestHit)
                            {
                                bestDir     = hit.Position - localToWorld.Position;
                                furthestHit = dist;
                                JobLogger.Log("Found a better way");
                            }
                        }
                        else     // this direction is unobstructed, return
                        {
                            unobstructedDirections[entityInQueryIndex] = hit.Position - localToWorld.Position;
                            JobLogger.Log("Found a way");
                            return;
                        }
                    }
                    unobstructedDirections[entityInQueryIndex] = bestDir;
                }).ScheduleParallel(batchRaycastJobHandle);
Exemple #23
0
        /// <summary>Gets a point on a navigable surface (either the current surface or a jumpable one) for the provided agent entity via the out hit parameter. Returns true if there is a navigable surface, false if not.</summary>
        public static bool GetPointOnNavigableSurface(Vector3 point, Entity agentEntity, Camera cam, PhysicsWorld physicsWorld, float raycastDistance, EntityManager entityManager, CollisionFilter filter, out Unity.Physics.RaycastHit hit)
        {
            var screenPointToRay = cam.ScreenPointToRay(point);

            var rayInput = new RaycastInput
            {
                Start  = screenPointToRay.origin,
                End    = screenPointToRay.GetPoint(raycastDistance),
                Filter = filter
            };

            if (!physicsWorld.CastRay(rayInput, out hit) || hit.RigidBodyIndex == -1)
            {
                return(false);
            }

            if (!NavMesh.SamplePosition(hit.Position, out var navMeshHit, 1, NavMesh.AllAreas))
            {
                return(false);
            }

            var hitSurfaceEntity = physicsWorld.Bodies[hit.RigidBodyIndex].Entity;

            if (hitSurfaceEntity == Entity.Null)
            {
                return(false);
            }

            if (!entityManager.HasComponent <Parent>(agentEntity))
            {
                return(false);
            }

            var surfaceEntity = entityManager.GetComponentData <Parent>(agentEntity).Value;

            if (surfaceEntity == Entity.Null)
            {
                return(false);
            }

            if (surfaceEntity == hitSurfaceEntity)
            {
                return(true);
            }

            if (!entityManager.HasComponent <NavJumpableBufferElement>(surfaceEntity))
            {
                return(false);
            }

            var jumpableSurfaces = entityManager.GetBuffer <NavJumpableBufferElement>(surfaceEntity);

            for (var i = 0; i < jumpableSurfaces.Length; ++i)
            {
                if (hitSurfaceEntity == jumpableSurfaces[i])
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #24
0
        public static bool RayCast <T>(ref T target, RaycastInput input) where T : struct, ICollidable
        {
            var collector = new AnyHitCollector <RaycastHit>(sfloat.One);

            return(target.CastRay(input, ref collector));
        }
            bool raycastHitToWall_
            (
                ref PhysicsVelocity v, ref float3 pos, ref quaternion rot, float dt,
                float3 origin, float3 gndray, float bodySize, float3 fwddir,
                Entity ent, CollisionFilter filter,
                ComponentDataFromEntity <Bone.MainEntityLinkData> mainEntities
            )
            {
                var h = raycast(ref this.CollisionWorld, origin, gndray, ent, filter, mainEntities);

                //var (isHit, hit) = raycast( ref this.CollisionWorld, origin, gndray, ent, filter );

                if (h.isHit)
                {
                    var newposrot = caluclateWallPosture
                                    //var (newpos, newrot) = caluclateWallPosture
                                        (origin, h.hit.Position, h.hit.SurfaceNormal, fwddir, bodySize);

                    var rdt = math.rcp(dt);
                    v.Linear = (newposrot.pos - pos) * rdt;
                    //pos = newposrot.pos;

                    //var invprev = math.inverse( newposrot.rot );
                    //var drot = math.mul( invprev, rot );
                    //var angle = math.acos( drot.value.w ) * 2.0f;
                    //var sin = math.sin( angle );
                    //var axis = drot.value.As_float3() * math.rcp( sin );
                    //var invprev = math.inverse( newposrot.rot );
                    //var drot = math.mul( invprev, rot );
                    //var axis = drot.value.As_float3();
                    //var angle = math.lengthsq( drot );
                    //v.Angular = axis * ( angle * rdt );
                    v.Angular = float3.zero;
                    rot       = newposrot.rot;
                }

                return(h.isHit);


                HitFlagAndResult raycast
                //( bool isHit, RaycastHit hit) raycast
                (
                    ref PhysicsWorld cw, float3 origin_, float3 ray_, Entity ent_, CollisionFilter filter_,
                    ComponentDataFromEntity <Bone.MainEntityLinkData> mainEntities_
                )
                {
                    var hitInput = new RaycastInput
                    {
                        Start  = origin_,
                        End    = origin_ + ray_,
                        Filter = filter_,
                    };
                    var collector = new ClosestHitExcludeSelfCollector <RaycastHit>(1.0f, ent, mainEntities_);

                    //var collector = new ClosestHitCollector<RaycastHit>( 1.0f );
                    /*var isHit = */
                    cw.CastRay(hitInput, ref collector);

                    return(new HitFlagAndResult {
                        isHit = collector.NumHits > 0, hit = collector.ClosestHit
                    });
                    //return (collector.NumHits > 0, collector.ClosestHit);
                }

                PosAndRot caluclateWallPosture
                //( float3 newpos, quaternion newrot) caluclateWallPosture
                    (float3 o, float3 p, float3 n, float3 up, float r)
                {
                    var f = p - o;
                    var w = f - math.dot(f, n) * n;

                    var upsign = math.sign(math.dot(up, w));
                    var newfwd = math.select(up, math.normalize(w * upsign), math.lengthsq(w) > 0.001f);
                    //var newfwd = math.lengthsq(w) > 0.001f ? math.normalize( w * math.sign( math.dot( up, w ) ) ) : up;
                    var newpos = p + n * r;
                    var newrot = quaternion.LookRotation(newfwd, n);

                    return(new PosAndRot {
                        pos = newpos, rot = newrot
                    });
                    //return (newpos, newrot);
                }
            }
Exemple #26
0
        // Update is called once per frame
        protected override void OnUpdate()
        {
            // Make sure the world has finished building before querying it
            CreatePhysicsWorldSystem.FinalJobHandle.Complete();

            PhysicsWorld world = CreatePhysicsWorldSystem.PhysicsWorld;

            Entities.ForEach((VehicleMechanics mechanics) =>
            {
                if (mechanics.wheels.Count == 0)
                {
                    return;
                }

                Entity ce = mechanics.chassisEntity;
                if (ce == Entity.Null)
                {
                    return;
                }

                int ceIdx = world.GetRigidBodyIndex(ce);
                if (-1 == ceIdx || ceIdx >= world.NumDynamicBodies)
                {
                    return;
                }

                //float ceMass = world.GetMass(ceIdx);
                float3 cePosition     = EntityManager.GetComponentData <Translation>(ce).Value;
                quaternion ceRotation = EntityManager.GetComponentData <Rotation>(ce).Value;
                float3 ceCenterOfMass = world.GetCenterOfMass(ceIdx);
                float3 ceUp           = math.mul(ceRotation, mechanics.chassisUp);
                float3 ceForward      = math.mul(ceRotation, mechanics.chassisForward);
                float3 ceRight        = math.mul(ceRotation, mechanics.chassisRight);

                var rayResults    = new NativeArray <RaycastHit>(mechanics.wheels.Count, Allocator.TempJob);
                var rayVelocities = new NativeArray <float3>(mechanics.wheels.Count, Allocator.TempJob);

                // Collect the RayCast results
                var rayInputs          = new NativeArray <RaycastInput>(mechanics.wheels.Count, Allocator.TempJob);
                CollisionFilter filter = world.GetCollisionFilter(ceIdx);
                for (int i = 0; i < mechanics.wheels.Count; i++)
                {
                    GameObject weGO = mechanics.wheels[i];

                    float3 wheelCurrentPos = weGO.transform.position;

                    float3 rayStart = weGO.transform.parent.position;
                    float3 rayEnd   = (-ceUp * (mechanics.suspensionLength + mechanics.wheelBase)) + rayStart;

                    if (mechanics.drawDebugInformation)
                    {
                        Debug.DrawRay(rayStart, rayEnd - rayStart);
                    }

                    rayInputs[i] = new RaycastInput
                    {
                        Start  = rayStart,
                        End    = rayEnd,
                        Filter = filter
                    };
                }
                JobHandle rayJobHandle = ScheduleBatchRayCast(world.CollisionWorld, rayInputs, rayResults);
                rayJobHandle.Complete();
                for (int i = 0; i < mechanics.wheels.Count; i++)
                {
                    RaycastHit rayResult = rayResults[i];

                    rayVelocities[i] = float3.zero;
                    if (rayResult.RigidBodyIndex != -1)
                    {
                        float3 wheelPos = rayResult.Position;
                        wheelPos       -= (cePosition - ceCenterOfMass);

                        float3 velocityAtWheel = world.GetLinearVelocity(ceIdx, wheelPos);
                        rayVelocities[i]       = velocityAtWheel;
                    }
                }
                rayInputs.Dispose();


                // Calculate a simple slip factor based on chassis tilt.
                float slopeSlipFactor = math.pow(math.abs(math.dot(ceUp, math.up())), 4.0f);

                // Proportional apply velocity changes to each wheel
                float invWheelCount = 1.0f / mechanics.wheels.Count;
                for (int i = 0; i < mechanics.wheels.Count; i++)
                {
                    GameObject weGO = mechanics.wheels[i];

                    float3 rayStart = weGO.transform.parent.position;
                    float3 rayEnd   = (-ceUp * (mechanics.suspensionLength + mechanics.wheelBase)) + rayStart;

                    float3 rayDir = rayEnd - rayStart;

                    RaycastHit rayResult = rayResults[i];
                    //float3 velocityAtWheel = rayVelocities[i];

                    float3 wheelPos = rayResult.Position;
                    wheelPos       -= (cePosition - ceCenterOfMass);

                    float3 velocityAtWheel = world.GetLinearVelocity(ceIdx, wheelPos);

                    float3 weUp      = ceUp;
                    float3 weRight   = ceRight;
                    float3 weForward = ceForward;

                    #region handle wheel steering
                    {
                        bool bIsSteeringWheel = mechanics.steeringWheels.Contains(weGO);
                        if (bIsSteeringWheel)
                        {
                            float steeringAngle = math.radians(mechanics.steeringAngle);
                            //if((mechanics.steeringWheels.IndexOf(weGO)+1) > (0.5f * mechanics.steeringWheels.Count))
                            //    steeringAngle = -steeringAngle;

                            quaternion wRotation = quaternion.AxisAngle(ceUp, steeringAngle);
                            weRight   = math.rotate(wRotation, weRight);
                            weForward = math.rotate(wRotation, weForward);

                            weGO.transform.localRotation = quaternion.AxisAngle(mechanics.chassisUp, steeringAngle);
                        }
                    }
                    #endregion

                    float currentSpeedUp      = math.dot(velocityAtWheel, weUp);
                    float currentSpeedForward = math.dot(velocityAtWheel, weForward);
                    float currentSpeedRight   = math.dot(velocityAtWheel, weRight);

                    #region handle wheel rotation
                    {
                        var rGO = weGO.transform.GetChild(0);
                        if (rGO)
                        {
                            bool isDriven    = (mechanics.driveEngaged && mechanics.driveWheels.Contains(weGO));
                            float weRotation = isDriven
                                ? (mechanics.driveDesiredSpeed / mechanics.wheelBase)
                                : (currentSpeedForward / mechanics.wheelBase);

                            weRotation = math.radians(weRotation);
                            rGO.transform.localRotation *= quaternion.AxisAngle(mechanics.chassisRight, weRotation);
                        }
                    }
                    #endregion


                    float3 wheelCurrentPos = weGO.transform.position;
                    bool hit = !math.all(rayResult.SurfaceNormal == float3.zero);
                    if (!hit)
                    {
                        float3 wheelDesiredPos  = (-ceUp * mechanics.suspensionLength) + rayStart;
                        weGO.transform.position = math.lerp(wheelCurrentPos, wheelDesiredPos, mechanics.suspensionDamping / mechanics.suspensionStrength);
                    }
                    else
                    {
                        // remove the wheelbase to get wheel position.
                        float fraction = rayResult.Fraction - (mechanics.wheelBase) / (mechanics.suspensionLength + mechanics.wheelBase);

                        float3 wheelDesiredPos  = math.lerp(rayStart, rayEnd, fraction);
                        weGO.transform.position = math.lerp(wheelCurrentPos, wheelDesiredPos, mechanics.suspensionDamping / mechanics.suspensionStrength);

                        #region Suspension
                        {
                            // Calculate and apply the impulses
                            var posA = rayEnd;
                            var posB = rayResult.Position;
                            var lvA  = currentSpeedUp * weUp;// world.GetLinearVelocity(ceIdx, posA);
                            var lvB  = world.GetLinearVelocity(rayResult.RigidBodyIndex, posB);

                            var impulse     = mechanics.suspensionStrength * (posB - posA) + mechanics.suspensionDamping * (lvB - lvA);
                            impulse         = impulse * invWheelCount;
                            float impulseUp = math.dot(impulse, weUp);

                            // Suspension shouldn't necessarily pull the vehicle down!
                            float downForceLimit = -0.25f;
                            if (downForceLimit < impulseUp)
                            {
                                impulse = impulseUp * weUp;

                                world.ApplyImpulse(ceIdx, impulse, posA);
                                //world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, posB);

                                if (mechanics.drawDebugInformation)
                                {
                                    Debug.DrawRay(wheelDesiredPos, impulse, Color.green);
                                }
                            }
                        }
                        #endregion

                        #region Sideways friction
                        {
                            float deltaSpeedRight = (0.0f - currentSpeedRight);
                            deltaSpeedRight       = math.clamp(deltaSpeedRight, -mechanics.wheelMaxImpulseRight, mechanics.wheelMaxImpulseRight);
                            deltaSpeedRight      *= mechanics.wheelFrictionRight;
                            deltaSpeedRight      *= slopeSlipFactor;

                            float3 impulse      = deltaSpeedRight * weRight;
                            float effectiveMass = world.GetEffectiveMass(ceIdx, impulse, wheelPos);
                            impulse             = impulse * effectiveMass * invWheelCount;

                            world.ApplyImpulse(ceIdx, impulse, wheelPos);
                            world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, wheelPos);

                            if (mechanics.drawDebugInformation)
                            {
                                Debug.DrawRay(wheelDesiredPos, impulse, Color.red);
                            }
                        }
                        #endregion

                        #region Drive
                        {
                            if (mechanics.driveEngaged && mechanics.driveWheels.Contains(weGO))
                            {
                                float deltaSpeedForward = (mechanics.driveDesiredSpeed - currentSpeedForward);
                                deltaSpeedForward       = math.clamp(deltaSpeedForward, -mechanics.wheelMaxImpulseForward, mechanics.wheelMaxImpulseForward);
                                deltaSpeedForward      *= mechanics.wheelFrictionForward;
                                deltaSpeedForward      *= slopeSlipFactor;

                                float3 impulse = deltaSpeedForward * weForward;

                                float effectiveMass = world.GetEffectiveMass(ceIdx, impulse, wheelPos);
                                impulse             = impulse * effectiveMass * invWheelCount;

                                world.ApplyImpulse(ceIdx, impulse, wheelPos);
                                world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, wheelPos);

                                if (mechanics.drawDebugInformation)
                                {
                                    Debug.DrawRay(wheelDesiredPos, impulse, Color.blue);
                                }
                            }
                        }
                        #endregion
                    }
                }

                rayResults.Dispose();
                rayVelocities.Dispose();
            });
        }
Exemple #27
0
 public static new bool RayCast(RaycastInput input, out RaycastOutput output) => ToolBase.RayCast(input, out output);
        protected override void OnUpdate()
        {
            // Raycast to find potential clicked block

            Pointer pointer = PointerInput.GetPointer();

            if (!pointer.Pressed)
            {
                return;
            }

            // Collision world
            CollisionWorld collisionWorld = this.buildPhysicsWorldSystem.PhysicsWorld.CollisionWorld;

            // Ray
            RaycastInput input = new RaycastInput()
            {
                Start  = pointer.WorldPosition,
                End    = pointer.WorldPosition + (pointer.WorldDirection * 1000f),
                Filter = new CollisionFilter()
                {
                    BelongsTo    = PhysicsCategories.POINTER,
                    CollidesWith = PhysicsCategories.BLOCK_POINTER,
                }
            };

            // Output hit
            NativeArray <RaycastHit> hit = new NativeArray <RaycastHit>(1, Allocator.TempJob);

            // Raycast job
            PointerRaycastJob pointerRaycastJob = new PointerRaycastJob()
            {
                collisionWorld = collisionWorld,
                input          = input,
                outHit         = hit,
            };
            JobHandle pointerRaycastHandle = pointerRaycastJob.Schedule(this.Dependency);

            // Get player current node
            NativeArray <PlayerNavigationNode> currentNode = new NativeArray <PlayerNavigationNode>(1, Allocator.TempJob);
            GetCurrentNodeJob getCurrentNodeJob            = new GetCurrentNodeJob()
            {
                outCurrentNode     = currentNode,
                playerMovementType = GetArchetypeChunkComponentType <PlayerMovementData>(true),
            };
            JobHandle getCurrentNodeHandle = getCurrentNodeJob.ScheduleParallel(this.playerQuery, pointerRaycastHandle);

            getCurrentNodeHandle.Complete();

            // Request path job
            RequestPathJob requestPathJob = new RequestPathJob()
            {
                hit                = hit,
                currentNode        = currentNode,
                navigationGridType = GetArchetypeChunkComponentType <NavigationGridData>(false),
                nodeBufferType     = GetArchetypeChunkBufferType <AStarNodeElement>(true),
            };
            JobHandle requestPathHandle = requestPathJob.ScheduleParallel(this.gridQuery, getCurrentNodeHandle);

            this.Dependency = requestPathHandle;
        }
Exemple #29
0
        // Essential Tool Functions
        protected override void OnToolUpdate()
        {
            base.OnToolUpdate();

            Ray          ray   = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastInput input = new RaycastInput(ray, Camera.main.farClipPlane);

            input.m_ignoreSegmentFlags       = NetSegment.Flags.None;
            input.m_ignoreNodeFlags          = NetNode.Flags.All;
            input.m_ignoreParkFlags          = DistrictPark.Flags.All;
            input.m_ignorePropFlags          = PropInstance.Flags.All;
            input.m_ignoreTreeFlags          = TreeInstance.Flags.All;
            input.m_ignoreCitizenFlags       = CitizenInstance.Flags.All;
            input.m_ignoreVehicleFlags       = Vehicle.Flags.Created;
            input.m_ignoreBuildingFlags      = Building.Flags.All;
            input.m_ignoreDisasterFlags      = DisasterData.Flags.All;
            input.m_ignoreTransportFlags     = TransportLine.Flags.All;
            input.m_ignoreParkedVehicleFlags = VehicleParked.Flags.All;
            input.m_ignoreTerrain            = true;
            RayCast(input, out RaycastOutput output);
            m_hover = output.m_netSegment;

            if (m_newSeg1 != 0 && m_newSeg2 != 0)
            {
                NetSegment s1 = GetSegment(m_newSeg1);
                NetSegment s2 = GetSegment(m_newSeg2);

                NetNode a = GetNode(s1.m_startNode);
                NetNode b = GetNode(s2.m_endNode);
                NetNode c = GetNode(s2.m_startNode);

                if ((a.m_problems | b.m_problems | c.m_problems) == Notification.Problem.RoadNotConnected)
                {
                    InvertSegment(m_newSeg1);
                    InvertSegment(m_newSeg2);
                }

                m_newSeg1 = 0;
                m_newSeg2 = 0;
                enabled   = false;
                UIView.Find("E3A").Unfocus();
                UIView.Find("E3B").Unfocus();
                mode = 0;
                ToolsModifierControl.SetTool <DefaultTool>();
            }

            if (m_hover != 0)
            {
                if (mode == 1)
                {
                    //Snap to location on segment
                    Bezier3    bezierx = new Bezier3();
                    NetSegment seg     = GetSegment(m_hover);
                    bezierx.a = NetManager.instance.m_nodes.m_buffer[seg.m_startNode].m_position;
                    bezierx.d = NetManager.instance.m_nodes.m_buffer[seg.m_endNode].m_position;

                    bool smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[seg.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;
                    bool smoothEnd   = (Singleton <NetManager> .instance.m_nodes.m_buffer[seg.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;

                    NetSegment.CalculateMiddlePoints(bezierx.a, seg.m_startDirection, bezierx.d, seg.m_endDirection, smoothStart, smoothEnd, out Vector3 b, out Vector3 c);

                    bezierx.b = b;
                    bezierx.c = c;

                    float iterations       = 40f; // Could be anywhere 0-100. Maybe configurable at a later point.
                    float time             = 0f;
                    float shortestDistance = 1000f;
                    for (float i = 0f; i < iterations; i++)
                    {
                        float   ttime     = (i + 1f) / iterations;
                        Vector3 testPoint = bezierx.Position(ttime);
                        float   distance  = Vector3.Distance(testPoint, output.m_hitPos);
                        if (distance < shortestDistance)
                        {
                            shortestDistance = distance;
                            time             = ttime;
                            m_snapFakeNode   = testPoint;
                        }
                    }

                    // If x < 0.1f or x > 0.9f, display a warning telling people the segment may start to glitch out? perhaps over a certain length? <0.1m?
                    m_errors = time * seg.m_averageLength < 3.0f || seg.m_averageLength - (time * seg.m_averageLength) < 3.0f;
                    pulsating++;

                    if (Input.GetMouseButtonUp(0) && Mathf.Abs(0.5f - time) < 0.5)
                    {
                        if (!NodeInsertion(m_hover, time))
                        {
                            Debug.LogError(":(");
                            return;
                        }
                    }
                }
                else
                {
                    if (Input.GetMouseButtonUp(0))
                    {
                        if (m_seg1 == 0)
                        {
                            m_seg1 = m_hover;
                        }
                        else
                        {
                            m_seg2 = m_hover;
                        }
                    }
                    else if (Input.GetMouseButtonUp(1))
                    {
                        if (m_seg2 != 0)
                        {
                            m_seg2 = 0;
                        }
                        else if (m_seg1 != 0)
                        {
                            m_seg1 = 0;
                        }
                    }
                }
            }

            if (Input.GetKeyUp(KeyCode.Return))
            {
                if (!Intersection(m_seg1, m_seg2))
                {
                    Debug.LogError(":(");
                }
                enabled = false;
                ToolsModifierControl.SetTool <DefaultTool>();
                m_seg1 = 0;
                m_seg2 = 0;
                UIView.Find("E3A").Unfocus();
                UIView.Find("E3B").Unfocus();
            }
        }
 public bool CastRay <T>(RaycastInput input, ref T collector) where T : struct, ICollector <RaycastHit>
 {
     return(CollisionWorld.CastRay(input, ref collector));
 }
Exemple #31
0
        protected override void OnUpdate()
        {
            var commandBuffer = barrier.CreateCommandBuffer().ToConcurrent();
            var defaultBasis  = World.GetExistingSystem <NavBasisSystem>().DefaultBasis;

            // Below job is needed because Unity.Physics removes the Parent
            // component for dynamic bodies.
            Entities
            .WithNone <Parent>()
            .ForEach((Entity entity, int entityInQueryIndex, in NavSurface surface) =>
            {
                if (surface.Basis.Equals(Entity.Null))
                {
                    commandBuffer.AddComponent(entityInQueryIndex, entity, new Parent
                    {
                        Value = defaultBasis
                    });
                }
                else
                {
                    commandBuffer.AddComponent(entityInQueryIndex, entity, new Parent
                    {
                        Value = surface.Basis
                    });
                }

                commandBuffer.AddComponent <LocalToParent>(entityInQueryIndex, entity);
            })
            .WithoutBurst()
            .WithName("NavAddParentToSurfaceJob")
            .ScheduleParallel();

            barrier.AddJobHandleForProducer(Dependency);

            // Below job is needed so users don't have to manually add the
            // Parent and LocalToParent components when spawning agents.
            Entities
            .WithNone <NavHasProblem, Parent>()
            .ForEach((Entity entity, int entityInQueryIndex, in NavAgent agent) =>
            {
                commandBuffer.AddComponent <Parent>(entityInQueryIndex, entity);
                commandBuffer.AddComponent <LocalToParent>(entityInQueryIndex, entity);
            })
            .WithoutBurst()
            .WithName("NavAddParentToAgentJob")
            .ScheduleParallel();

            barrier.AddJobHandleForProducer(Dependency);

            // Below job is needed because Unity.Transforms assumes that
            // children should be scaled by their surface by automatically
            // providing them with a CompositeScale.
            Entities
            .WithAll <CompositeScale>()
            .WithAny <NavSurface, NavBasis>()
            .ForEach((Entity entity, int entityInQueryIndex) =>
            {
                commandBuffer.RemoveComponent <CompositeScale>(entityInQueryIndex, entity);
            })
            .WithName("NavRemoveCompositeScaleJob")
            .ScheduleParallel();

            barrier.AddJobHandleForProducer(Dependency);

            var elapsedSeconds       = (float)Time.ElapsedTime;
            var physicsWorld         = buildPhysicsWorld.PhysicsWorld;
            var jumpBufferFromEntity = GetBufferFromEntity <NavJumpBufferElement>();
            var map = needsSurfaceMap;

            Dependency = JobHandle.CombineDependencies(Dependency, buildPhysicsWorld.GetOutputDependency());

            Entities
            .WithNone <NavHasProblem, NavFalling, NavJumping>()
            .WithAll <NavNeedsSurface, LocalToParent>()
            .WithReadOnly(physicsWorld)
            .WithNativeDisableParallelForRestriction(jumpBufferFromEntity)
            .WithNativeDisableContainerSafetyRestriction(map)
            .ForEach((Entity entity, int entityInQueryIndex, ref NavAgent agent, ref Parent surface, ref Translation translation, in LocalToWorld localToWorld) =>
            {
                if (
                    !surface.Value.Equals(Entity.Null) &&
                    map.TryGetValue(entity.Index, out bool needsSurface) &&
                    !map.TryAdd(entity.Index, false)
                    )
                {
                    return;
                }

                var rayInput = new RaycastInput
                {
                    Start  = localToWorld.Position + agent.Offset,
                    End    = -localToWorld.Up * NavConstants.SURFACE_RAYCAST_DISTANCE_MAX,
                    Filter = new CollisionFilter()
                    {
                        BelongsTo    = NavUtil.ToBitMask(NavConstants.COLLIDER_LAYER),
                        CollidesWith = NavUtil.ToBitMask(NavConstants.SURFACE_LAYER),
                    }
                };

                if (!physicsWorld.CastRay(rayInput, out RaycastHit hit))
                {
                    if (++agent.SurfaceRaycastCount >= NavConstants.SURFACE_RAYCAST_MAX)
                    {
                        agent.FallSeconds = elapsedSeconds;

                        commandBuffer.RemoveComponent <NavNeedsSurface>(entityInQueryIndex, entity);
                        commandBuffer.AddComponent <NavFalling>(entityInQueryIndex, entity);
                    }

                    return;
                }

                agent.SurfaceRaycastCount = 0;
                surface.Value             = physicsWorld.Bodies[hit.RigidBodyIndex].Entity;
                commandBuffer.RemoveComponent <NavNeedsSurface>(entityInQueryIndex, entity);

                if (!jumpBufferFromEntity.Exists(entity))
                {
                    return;
                }
                var jumpBuffer = jumpBufferFromEntity[entity];
                if (jumpBuffer.Length < 1)
                {
                    return;
                }

                translation.Value = jumpBuffer[0].Value + agent.Offset;

                jumpBuffer.Clear();

                commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity);
            })
            .WithName("NavSurfaceTrackingJob")
            .ScheduleParallel();

            barrier.AddJobHandleForProducer(Dependency);
        }
Exemple #32
0
 public bool CastRay(RaycastInput input, out RaycastHit closestHit) => QueryWrappers.RayCast(ref this, input, out closestHit);
Exemple #33
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var hubUids  = chunk.GetNativeArray(HubUids);
                var counters = chunk.GetNativeArray(Counters);
                var rates    = chunk.GetNativeArray(Rates);
                var marks    = chunk.GetNativeArray(Marks);
                var pos      = chunk.GetNativeArray(Positions);

                for (var i = 0; i < chunk.Count; ++i)
                {
                    if (CurrentTime - marks[i].Value.x < marks[i].Value.y)
                    {
                        continue;
                    }

                    var val = counters[i].Value + 1;
                    counters[i] = new JobGenerationCounter {
                        Value = val
                    };
                    var mark = marks[i].Value;
                    mark.x   = CurrentTime;
                    mark.y   = -math.log(1 - Rand.NextFloat(0, 1)) / rates[i].Value;
                    marks[i] = new JobGenerationTimeMark {
                        Value = mark
                    };
                    var origin      = pos[i].Value;
                    var destination = GetDestination();
                    var dist        = math.lengthsq(destination - new float3(origin.x, 0, origin.z));
                    var input       = new RaycastInput
                    {
                        Start  = new float3(destination.x, 2000, destination.z),
                        End    = destination,
                        Filter = new CollisionFilter
                        {
                            BelongsTo    = CollisionGroups.Cast,
                            CollidesWith = CollisionGroups.Buildings
                        }
                    };
                    while (dist < 10000 || World.CastRay(input, out _))
                    {
                        destination = GetDestination();
                        dist        = math.lengthsq(destination - new float3(origin.x, 0, origin.z));
                        input.Start = new float3(destination.x, 2000, destination.z);
                        input.End   = destination;
                    }
                    CreatedJobs.BeginForEachIndex(chunkIndex);
                    CreatedJobs.Write(new JobEntityProxy
                    {
                        id = new JobUID {
                            Value = counters[i].Value
                        },
                        created = new JobCreationTime {
                            Value = CurrentTime
                        },
                        origin = new JobOrigin {
                            Value = pos[i].Value
                        },
                        destination = new JobDestination {
                            Value = destination
                        },
                        costFunction = SimulationType == SimulationTypeValue.Delivery
                            ? CostFunction.GetDelivery(Reward())
                            : CostFunction.GetEmergency(Rand),
                        hub = new ParentHub {
                            Value = hubUids[i].Value
                        }
                    });
                    CreatedJobs.EndForEachIndex();
                }
            }
        public override void SimulationStep()
        {
            base.SimulationStep();

            var mouseRayValid = !UIView.IsInsideUI() && Cursor.visible && !_cursorInSecondaryPanel;

            if (mouseRayValid)
            {
                var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
                var mouseRayLength = Camera.main.farClipPlane;
                var rayRight = Camera.main.transform.TransformDirection(Vector3.right);

                var defaultService = new RaycastService(ItemClass.Service.Road, ItemClass.SubService.None, ItemClass.Layer.Default);
                var input = new RaycastInput(mouseRay, mouseRayLength)
                {
                    m_rayRight = rayRight,
                    m_netService = defaultService,
                    m_ignoreNodeFlags = NetNode.Flags.None,
                    m_ignoreSegmentFlags = NetSegment.Flags.Untouchable
                };
                RaycastOutput output;
                if (!RayCast(input, out output))
                {
                    _hoveredSegmentIdx = 0;
                    _hoveredNetNodeIdx = 0;
                    return;
                }

                _hoveredNetNodeIdx = output.m_netNode;

                _hoveredSegmentIdx = output.m_netSegment;
            }

            if (_toolMode == ToolMode.None)
            {
                ToolCursor = null;
            }
            else
            {
                var netTool = ToolsModifierControl.toolController.Tools.OfType<NetTool>().FirstOrDefault(nt => nt.m_prefab != null);

                if (netTool != null && mouseRayValid)
                {
                    ToolCursor = netTool.m_upgradeCursor;
                }
            }
        }
Exemple #35
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        inputDeps.Complete();

        var physicsWorld   = m_BuildPhysicsWorldSystem.PhysicsWorld;
        var PredictingTick = World.GetExistingSystem <GhostPredictionSystemGroup>().PredictingTick;

        Entities
        .ForEach((
                     ref CharacterControllerComponentData ccData,
                     ref CharacterControllerInitializationData ccInitData,
                     ref CharacterControllerMoveQuery ccMoveQuery,
                     ref CharacterControllerVelocity ccVelocity,
                     in PredictedGhostComponent predictedGhostComponent) =>
        {
            if (!GhostPredictionSystemGroup.ShouldPredict(PredictingTick, predictedGhostComponent))
            {
                return;
            }
            if (!ccMoveQuery.FollowGround)
            {
                return;
            }

            var vel = ccVelocity.Velocity;
            if (math.lengthsq(vel) == 0.0f)
            {
                return;
            }

            var skinWidth       = ccData.SkinWidth;
            var startPos        = ccMoveQuery.StartPosition - math.up() * skinWidth;
            var dir             = math.normalizesafe(vel);
            var horizDir        = new float3(dir.x, 0.0f, dir.z);
            var len             = ccInitData.CapsuleRadius;
            var endPos          = startPos + len * dir;
            var slopeAdjustment = math.up() * len * math.tan(ccData.MaxSlope);
            var rayInput        = new RaycastInput
            {
                Start  = endPos + slopeAdjustment,
                End    = endPos - slopeAdjustment,
                Filter = new CollisionFilter {
                    BelongsTo = 1, CollidesWith = 1, GroupIndex = 0
                }
            };
            var rayHit = new RaycastHit();
            if (!physicsWorld.CastRay(rayInput, out rayHit))
            {
                return;
            }

            var newDir      = math.normalize(rayHit.Position - startPos);
            var newHorizDir = new float3(newDir.x, 0.0f, newDir.z);
            var newVel      = newDir * math.length(vel) * math.length(horizDir) / math.length(newHorizDir);
            if (math.abs(newVel.y) > 0.01f)
            {
                ccVelocity.Velocity = newVel;
            }
        }).Run();

        return(default);