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); }
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
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)); }
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; }
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; }
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); } }
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); }
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); }
public bool CastRay(RaycastInput input) => QueryWrappers.RayCast(ref this, input);
public bool CastRay(RaycastInput input, ref NativeList <RaycastHit> allHits) => QueryWrappers.RayCast(ref this, input, ref allHits);
public bool CastRay <T>(RaycastInput input, ref T collector) where T : struct, ICollector <RaycastHit> { return(Collider != null && Collider->CastRay(input, ref collector)); }
public bool DoRayCast(RaycastInput input, out RaycastOutput output) { return(RayCast(input, out output)); }
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(); }
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);
/// <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); }
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); } }
// 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(); }); }
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; }
// 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)); }
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); }
public bool CastRay(RaycastInput input, out RaycastHit closestHit) => QueryWrappers.RayCast(ref this, input, out closestHit);
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; } } }
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);