private static Vertex CreateOrFindVertex(float3 pointCoord, out bool isOldVertex, int handle) { int vertHandle; Vertex vert; //Check if a Vertex already exists and assign it to the HalfEdge instead of creating a new. if (_geometry.DictVertices.Count != 0) { foreach (var v in _geometry.GetAllVertices()) { if (!pointCoord.Equals(v.VertData.Pos)) { continue; } isOldVertex = true; return(v); } //Create Vertice and VertHandle. vertHandle = handle; vert = new Vertex(vertHandle, pointCoord); } else { //Create Vertices and VertHandle. vertHandle = handle; vert = new Vertex(vertHandle, pointCoord); } isOldVertex = false; return(vert); }
private void OnSceneGUI() { if (Tools.current != Tool.Rect) { return; } var tar = target as TerminalAuthoring; if (tar == null) { return; } float3 center = tar.transform.position; float2 size = tar.Size * tar.TileSize; float3 pos = tar.transform.position; var col = ColorFromName(tar.name); Rect originalArea = new Rect(pos.xy, size); var newArea = RectUtils.ResizeRect(originalArea, Handles.DotHandleCap, Color.blue, col, HandleUtility.GetHandleSize(center) * .08f, tar.TileSize.y); float3 newCenter = PosHandle(center, tar.TileSize.y); if (!newCenter.Equals(tar.transform.position)) { tar.transform.position = newCenter; } if (newArea != originalArea) { tar.Size = (int2)(math.floor(newArea.size)); } }
public bool IsIdentical(LaserSegment other) { if (ReferenceEquals(null, other)) { return(false); } if (ReferenceEquals(this, other)) { return(true); } if (!(Ray.Equals(other.Ray) && Depth == other.Depth && Equals(Color, other.Color) && EmissionNormal.Equals(other.EmissionNormal) && Length.Equals(other.Length) && ImpactNormal.Equals(other.ImpactNormal) && Children.Count == other.Children.Count )) { return(false); } for (int i = 0; i < Children.Count; i++) { if (!Children[i].IsIdentical(other.Children[i])) { return(false); } } return(true); }
private void AssignModifiers(IReadOnlyList <Tile> tiles, Tile highest, Tile lowest) { // Calculate special tiles var remainingTiles = tiles.Count - 2; var specialTiles = remainingTiles > extraModifierChanceProbability ? Random.NextInt(0 + extraModifierChanceProbability, remainingTiles) : remainingTiles; // Remove the minimum regular tiles that are required specialTiles = specialTiles > minimumRegularRooms ? specialTiles - minimumRegularRooms : 0; CreateRooms(tiles, highest, lowest, specialTiles); _startPosition = lowest.BottomRectangle.Center; _endPosition = highest.BottomRectangle.Center; if (!_endPosition.Equals(_startPosition)) { return; } for (var i = tiles.Count - 1; i > 0; i--) { if (tiles[i].Type == TileType.Regular) { continue; } // Set endPosition to the last main room and stop looking for other positions _endPosition = tiles[i].BottomRectangle.Center; break; } }
protected override void OnUpdate() { Entities.ForEach((DynamicBuffer <PathPosition> pathPositionBuffer, ref Translation translation) => { if (pathPositionBuffer.Length > 0) { int2 nextPosition = pathPositionBuffer[pathPositionBuffer.Length - 1].position; float3 targetPosition = new float3(nextPosition.x + 0.5f, nextPosition.y + 0.5f, 0); // check if we're standing on the target if (targetPosition.Equals(translation.Value)) { pathPositionBuffer.RemoveAt(pathPositionBuffer.Length - 1); return; } float3 moveDir = math.normalize(targetPosition - translation.Value); float moveSpeed = 3f; translation.Value += moveDir * moveSpeed * Time.deltaTime; if (math.distance(translation.Value, targetPosition) < .1f) { //Debug.Log("moving to " + nextPosition); pathPositionBuffer.RemoveAt(pathPositionBuffer.Length - 1); } } }); }
private static float3 CalculateFinalOrientation( bool strafe, float3 strafeForward, float3 objectForward, float3 currentPointPosition, float3 previewPointPosition ) { if (strafe) { return(strafeForward); } else { float3 finalOrientation = currentPointPosition - previewPointPosition; if (finalOrientation.Equals(float3.zero)) { return(objectForward); } else { return(math.normalize(finalOrientation)); } } }
protected override JobHandle OnUpdate(JobHandle jobHandle) { float deltaTime = Time.DeltaTime; var ecb = _ecbSystem.CreateCommandBuffer().ToConcurrent(); jobHandle = Entities.ForEach(( Entity entity, int entityInQueryIndex, ref Velocity velocity, in Translation position, in Destination destination, in MoveSpeed moveSpeed) => { float3 dv = destination.Value - position.Value; if (dv.Equals(float3.zero)) { velocity.Value = float3.zero; ecb.RemoveComponent <Destination>(entityInQueryIndex, entity); } else { float3 normalVel = math.normalize(dv) * moveSpeed.Value; float3 teleportToDestinationVelocity = dv / deltaTime; if (math.lengthsq(teleportToDestinationVelocity) < math.lengthsq(normalVel) || math.any(math.isnan(normalVel))) { velocity.Value = teleportToDestinationVelocity; } else { velocity.Value = normalVel; } } })
//----------------------------------------------------------------------------- // Note: we use the zero vector to denote an unfilled cell in the grid. This means that if we were // to randomly pick (0, 0) as a sample, it would be ignored for the purposes of proximity-testing // and we might end up with another sample too close from (0, 0). This is a very minor issue. private bool IsFarEnough(float3 sample, float cellSize) { var posX = (int)(sample.x / cellSize); var posZ = (int)(sample.z / cellSize); int xmin = Mathf.Max(posX - 2, 0); int ymin = Mathf.Max(posZ - 2, 0); int xmax = Mathf.Min(posX + 2, m_DistWidth - 1); int ymax = Mathf.Min(posZ + 2, m_DistHeight - 1); for (int y = ymin; y <= ymax; y++) { for (int x = xmin; x <= xmax; x++) { float3 cell = m_Grid[y * m_DistWidth + x]; if (cell.Equals(new float3(0, 0, 0))) { continue; } float3 d = cell - sample; if (d.x * d.x + d.z * d.z < m_RadiusSquared) { return(false); } } } return(true); }
protected override void OnUpdate() { float deltaTime = Time.DeltaTime; float3 targetDir = float3.zero; EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager; Entities.ForEach((Entity entity, ref Translation translation, ref SpeedData speedData, ref EnemyTag enemyTag, ref HasTarget hasTarget) => { if (entityManager.Exists(hasTarget.targetEntity)) { Translation targetTranslation = World.DefaultGameObjectInjectionWorld.EntityManager.GetComponentData <Translation>(hasTarget.targetEntity); targetDir = math.normalize(targetTranslation.Value - translation.Value); translation.Value -= targetDir * speedData.speed * deltaTime; } else { if (targetDir.Equals(float3.zero)) { float3 targetPos = new float3(UnityEngine.Random.Range(-10, 10), 0, UnityEngine.Random.Range(-10, 10)); targetDir = math.normalize(targetPos - translation.Value); } translation.Value += targetDir * speedData.speed * deltaTime; } }); }
protected override void OnUpdate() { float movementX = Input.GetAxis("Horizontal"); float movementZ = Input.GetAxis("Vertical"); Entities.WithAll <AgentData>().ForEach((ref AgentData agentData, in Rotation rotation) => { float3 direction = new float3(movementX, 0, movementZ);// TODO:写在 Foreach 外时可能获得 NULL 值,但不知道原因 // var dir = math.normalize(math.mul(rotation.Value, direction)); // physicsVelocity.Linear = direction * 8 * deltaTime; if (direction.Equals(float3.zero)) { agentData.targetDirection = 0; } else { // direction 为 0 时,归一化返回 NULL agentData.targetDirection = math.normalize(math.mul(rotation.Value, direction)); } // float3 direction = new float3(movementX, 0, movementZ); // ccdata.currentDirection = math.normalize(math.mul(rotation.Value, direction)); // ccdata.currentMagnitude = 1.0f; // if (direction.Equals(float3.zero)) // { // ccdata.currentMagnitude = 0; // } }).ScheduleParallel(); }
public bool Equals(CoreData other) { if (!other.isValid || !isValid) { Debug.LogWarning("CoreData: comparing invalid cds"); return(false); } return(Name.Equals(other.Name) && BaseName.Equals(other.BaseName) && size.Equals(other.size) && scale.Equals(other.scale)); }
protected override void OnUpdate() { if (Utility.playerEntity.Equals(Entity.Null)) { return; } Entities.ForEach((ref TeleportComponent teleportComp, ref PlayerComponent playerComp, ref Translation pos) => { if (EntityManager.HasComponent <FadeInComponent>(Utility.playerEntity) || EntityManager.HasComponent <FadeOutComponent>(Utility.playerEntity)) { return; } // start if (_desiredPos.Equals(float3.zero)) { EntityManager.AddComponentData(Utility.playerEntity, new GamePauseComponent()); EntityManager.AddComponentData(Utility.playerEntity, new FadeInComponent(teleportComp.fadeInOutTime)); EntityManager.AddComponentData(Utility.playerEntity, new SubSceneControlComponent()); EntityManager.AddComponentData(Utility.playerEntity, new SubSceneLoadComponent() { type = (int)teleportComp.nextSubSceneType }); _desiredPos = GetTeleportPoint(teleportComp.sceneType, teleportComp.pointID); } // finish else if (pos.Value.Equals(_desiredPos)) { _curSubSceneType = teleportComp.nextSubSceneType; EntityManager.AddComponentData(Utility.playerEntity, new GameResumeComponent()); EntityManager.RemoveComponent <TeleportComponent>(Utility.playerEntity); EntityManager.RemoveComponent <SubSceneControlComponent>(Utility.playerEntity); playerComp.currentBehaviors ^= BehaviorState.teleport; _desiredPos = float3.zero; return; } teleportComp.elapsedTeleportTime += Time.DeltaTime; if (teleportComp.elapsedTeleportTime >= teleportComp.teleportTime) { // player pos.Value = _desiredPos; EntityManager.AddComponentData(Utility.playerEntity, new CameraSyncComponent(_desiredPos)); EntityManager.AddComponentData(Utility.playerEntity, new FadeOutComponent(teleportComp.fadeInOutTime)); EntityManager.AddComponentData(Utility.playerEntity, new SubSceneUnLoadComponent() { type = (int)teleportComp.curSubSceneType }); } }); }
bool PlayerPositionChanged() { var curPos = GetPlayerPosition(); var changed = !lastPlayerPosition.Equals(curPos); if (changed) { lastPlayerPosition = curPos; } return(changed); }
public bool Equals(SimpleMaterial other) { return(texAlbedo.Equals(other.texAlbedo) && texOpacity.Equals(other.texOpacity) && constAlbedo.Equals(other.constAlbedo) && constOpacity.Equals(other.constOpacity) && (twoSided == other.twoSided) && (blend == other.blend) && (transparent == other.transparent) && scale.Equals(other.scale) && offset.Equals(other.offset)); }
protected override void OnUpdate() { if (targetObject == null) { targetObject = GameObject.FindGameObjectWithTag("Target"); } tempTarget = targetObject.transform.position; float3 sepVelocity = new float3(0, 0, 0); float3 alignVelocity = new float3(0, 0, 0); float3 arriveVelocity = new float3(0, 0, 0); float3 velocitySum = new float3(0, 0, 0); Entities.WithAll <Skeleton>().ForEach((Entity entity, ref Translation skeletonTranslation, ref PhysicsVelocity velocity, ref Rotation rotation) => { //Code to run on all entities with the "Skeleton" tag NativeList <Entity> closestTargetsEntityList = new NativeList <Entity>(Allocator.Temp); NativeList <float3> closestTargetsPositionList = new NativeList <float3>(Allocator.Temp); NativeList <Vector3> closestTargetsVelocityList = new NativeList <Vector3>(Allocator.Temp); float3 skeletonPosition = skeletonTranslation.Value; float3 closestTargetPosition = float3.zero; //Cycle through all other skeletons units to find the ones in neighbour distance Entities.WithAll <Skeleton>().ForEach((Entity targetEntity, ref Translation targetTranslation, ref PhysicsVelocity targetVelocity) => { if (entity != null) { if (entity != targetEntity) { if (math.lengthsq(targetTranslation.Value - skeletonPosition) < (distance * distance)) { closestTargetsEntityList.Add(targetEntity); closestTargetsPositionList.Add(targetTranslation.Value); closestTargetsVelocityList.Add(targetVelocity.Angular); } } } }); sepVelocity = PerformSeparationBehavior(closestTargetsEntityList, closestTargetsPositionList, skeletonPosition, moveSpeed, velocity.Linear); arriveVelocity = PerformArrivalBehavior(tempTarget, skeletonPosition, moveSpeed, velocity.Linear); velocitySum = (sepVelocity + arriveVelocity + alignVelocity) * new float3(1, 0, 1); if (!(velocitySum.Equals(float3.zero))) { velocity.Linear += math.normalize(velocitySum); } closestTargetsEntityList.Dispose(); closestTargetsPositionList.Dispose(); closestTargetsVelocityList.Dispose(); }); }
private static bool WouldDeltaJumpTarget(float3 old, float3 delta, float3 target) { float3 fullMove = old + delta; if (target.Equals(fullMove)) { return(true); } float3 toTarget = target - fullMove; return(math.dot(delta, toTarget) < 0.0f); }
private void InitNeighbors() { Neighbors = new NativeArray <int>(Vertices.Length * 6, Allocator.Persistent); var neighborList = new List <Tuple <int, float3> > [Vertices.Length]; for (int i = 0; i < Vertices.Length; i++) { neighborList[i] = new List <Tuple <int, float3> >(); } for (int i = 0; i < Polygons.Count; i++) { var p = Polygons[i]; for (int j = 0; j < 3; j++) { int vertIndex = p.m_Vertices[(j + 1) % 3]; neighborList[p.m_Vertices[j]].Add(new Tuple <int, float3>(vertIndex, Vertices[vertIndex])); } } for (int i = 0; i < Vertices.Length; i++) { var pos = Vertices[i]; var forward = math.normalize(neighborList[i][0].Item2 - pos); neighborList[i].Sort(delegate(Tuple <int, float3> a, Tuple <int, float3> b) { float3 diffA = math.normalize(a.Item2 - pos); float3 diffB = math.normalize(b.Item2 - pos); float dotA = math.dot(diffA, forward); float dotB = math.dot(diffB, forward); float angleA = diffA.Equals(forward) ? 0 : math.acos(dotA); float angleB = diffB.Equals(forward) ? 0 : math.acos(dotB); angleA *= math.dot(pos, math.cross(forward, diffA)) >= 0 ? 1 : -1; angleB *= math.dot(pos, math.cross(forward, diffB)) >= 0 ? 1 : -1; return((int)math.sign(angleB - angleA)); }); for (int j = 0; j < 6; j++) { int index = i * 6 + j; if (j < neighborList[i].Count) { int n = neighborList[i][j].Item1; Neighbors[index] = n; } else { Neighbors[index] = -1; } } } }
// Apply the flocking behaviour using a buffer private ReynoldsMovementValues GetFlockingBehaviour(ref Translation agentTranslation, ref float3 preVelocity, ref DynamicBuffer <float3> nearbyCrowdPosList, ref DynamicBuffer <float3> nearbyCrowdVelList, ref ReynoldsFlockBehaviour flockBehaviour, ReynoldsMovementValues movement) { float3 move = float3.zero; // where the agent will move // Calculate Avoidance first float3 avoidance = CalculateAvoidance(ref agentTranslation.Value, ref nearbyCrowdPosList, ref flockBehaviour); //if the avoidance is not zero if (!avoidance.Equals(float3.zero)) { avoidance = math.normalize(avoidance); avoidance *= flockBehaviour.AvoidanceWeight; move += avoidance; //Debug.Log("Move after avoid: " +move); } // Calculate cohesion float3 cohesion = CalculateCohesion(ref agentTranslation.Value, ref preVelocity, ref nearbyCrowdPosList, ref nearbyCrowdVelList, ref flockBehaviour); if (!cohesion.Equals(float3.zero)) { //Debug.Log("Cohes Dst Sq: " +math.distancesq(float3.zero,cohesion)); //if the avoidance is not normalized (The square of the length of the position is greater than the square of the weights) if (math.distancesq(float3.zero, cohesion) > flockBehaviour.CohesionWeight * flockBehaviour.CohesionWeight) { //normalize the movement vector cohesion = math.normalize(cohesion); cohesion *= flockBehaviour.CohesionWeight; } move += cohesion; //Debug.Log("Move after cohes: " +move); } // May want to calculate alignment after, but not at time of writing this ReynoldsMovementValues movementValues = new ReynoldsMovementValues { flockMovement = move, seekMovement = movement.seekMovement, fleeMovement = movement.fleeMovement }; //Debug.Log("Flock stored: " +movementValues.flockMovement); return(movementValues); //movement.flockMovement = move; //float moveSpeed = 5f; //movement speed //agentTranslation.Value += move * moveSpeed * Time.deltaTime; //add movement to the translation //return move; }
public bool Equals(Noise other) => Seed == other.Seed && Octaves == other.Octaves && Lacunarity == other.Lacunarity && Persistence == other.Persistence && Scale == other.Scale && Weight == other.Weight && WeightMultiplier == other.WeightMultiplier && Offset.Equals(other.Offset) && FloorOffset == other.FloorOffset && HardFloorHeight == other.HardFloorHeight && HardFloorWeight == other.HardFloorWeight && TerraceHeight == other.TerraceHeight && TerraceWeight == other.TerraceWeight;
void Update() { if (entity != Entity.Null && !oldValue.Equals(this.movementMultiplier)) { manager.SetComponentData(entity, new PhysicsSpeedMultiplier { Value = movementMultiplier }); oldValue = movementMultiplier; EventCenter.MultiplierChangedEvent.Invoke(new MultiplierMessage() { Multiplier = movementMultiplier }); } }
/// <summary> /// creates a Float3Slider with the given arguments /// </summary> /// <param name="maxValue"></param> /// <param name="minValue"></param> public Float3Slider(float3 _minValue = new float3(), float3 _maxValue = new float3(), float3 value = new float3(), string sliderName = "Float3Slider", string maxValueName = "Max", string minValueName = "Min", string xLabel = "X Value", string yLabel = "Y Value", string zLabel = "Z Value") { MaxValue = _maxValue.Equals(_minValue) ? new float3(_minValue.x + 1f, _minValue.y + 1f, _minValue.z + 1f) : _maxValue; MinValue = _minValue; Value = value; SliderName = sliderName; MaxValueName = maxValueName; MinValueName = minValueName; XLabel = xLabel; YLabel = yLabel; ZLabel = zLabel; }
public static bool LinesIntersect(float3 line1, float3 line2, out float2 intersection) { intersection = float2.zero; if (line1.Equals(line2) || !TryGetDelta(new float2x2(line1.x, line1.y, line2.x, line2.y), out float delta)) { return(false); } intersection = new float2( (line2.y * line1.z - line1.y * line2.z) / delta, (line1.x * line2.z - line2.x * line1.z) / delta ); return(true); }
public float3 CompoteDesired(float3 formationLocation) { float3 desired = (formationLocation + m_desiredLocation); float d = math.distance(desired, m_currentLocation); if (d < 0.25f || m_velocity.Equals(float3.zero)) { return(float3.zero); } float3 v = (m_desiredLocation + formationLocation) - m_currentLocation; v = v - m_velocity; v = math.normalize(v); return(v); }
// matrix to transform point on a primitive from bake space into space of the shape static float4x4 GetPrimitiveBakeToShapeMatrix( float4x4 localToWorld, float4x4 shapeToWorld, ref float3 center, ref EulerAngles orientation, float3 scale, int3 basisPriority ) { if ( basisPriority.x == basisPriority.y || basisPriority.x == basisPriority.z || basisPriority.y == basisPriority.z ) { throw new ArgumentException(nameof(basisPriority)); } var localToBasis = float4x4.TRS(center, orientation, scale); // correct for imprecision in cases of no scale to prevent e.g., convex radius from being altered if (scale.Equals(new float3(1f))) { localToBasis.c0 = math.normalizesafe(localToBasis.c0); localToBasis.c1 = math.normalizesafe(localToBasis.c1); localToBasis.c2 = math.normalizesafe(localToBasis.c2); } var localToBake = math.mul(localToWorld, localToBasis); if (localToBake.HasNonUniformScale() || localToBake.HasShear()) { // deskew second longest axis with respect to longest axis localToBake[basisPriority[1]] = DeskewSecondaryAxis(localToBake[basisPriority[0]], localToBake[basisPriority[1]]); // recompute third axes from first two var n2 = math.normalizesafe( new float4(math.cross(localToBake[basisPriority[0]].xyz, localToBake[basisPriority[1]].xyz), 0f) ); localToBake[basisPriority[2]] = n2 * math.dot(localToBake[basisPriority[2]], n2); } var bakeToShape = math.mul(math.inverse(shapeToWorld), localToBake); // transform baked center/orientation (i.e. primitive basis) into shape space orientation.SetValue( quaternion.LookRotationSafe(bakeToShape[basisPriority[0]].xyz, bakeToShape[basisPriority[1]].xyz) ); center = bakeToShape.c3.xyz; return(bakeToShape); }
public int qtdObjects;//quantidade total de objetos nos objetos public void Execute(ref Translation pos, ref Rotation rot, ref FlockWho flockWho) { index = flockWho.flockValue + (flockWho.flockManagerValue) * flocksQuantityPerLayer; float3 velocity = GetFlockMovement(pos.Value, rot.Value, ref flockWho); //pegar o movimento/velocidade do flock (+ direcao) velocity.z = 0f; if (!velocity.Equals(float3.zero)) { rot.Value = quaternion.LookRotation(math.forward(rot.Value), velocity); //setar a rotacao } else { rot.Value = quaternion.LookRotation(math.forward(rot.Value), math.up()); //setar a rotacao } pos.Value += velocity * timeDT; //setar a posicao }
public bool Equals(LitMaterial other) { return(texAlbedo.Equals(other.texAlbedo) && texMetal.Equals(other.texMetal) && texNormal.Equals(other.texNormal) && texEmissive.Equals(other.texEmissive) && texSmoothness.Equals(other.texSmoothness) && texOpacity.Equals(other.texOpacity) && constAlbedo.Equals(other.constAlbedo) && constEmissive.Equals(other.constEmissive) && constOpacity.Equals(other.constOpacity) && constMetal.Equals(other.constMetal) && constSmoothness.Equals(other.constSmoothness) && normalMapZScale.Equals(other.normalMapZScale) && (twoSided == other.twoSided) && (transparent == other.transparent) && (triangleSortTransparent == other.triangleSortTransparent) && scale.Equals(other.scale) && offset.Equals(other.offset)); }
public bool CheckRay(float3 position, float3 direction, float3 currentDirection) { if (direction.Equals(-currentDirection)) { return(true); } var ray = new RaycastInput { Start = position, End = position + direction * 0.9f, Filter = new CollisionFilter { GroupIndex = 0, BelongsTo = 1u << 1, CollidesWith = 1u << 2 } }; return(PhysicsWorld.CastRay(ray)); }
public bool RaycastCheck(float3 position, float3 direction, float3 currentDirection) { if (direction.Equals(-currentDirection)) { return(true); } var ray = new RaycastInput() { Start = position, End = position + (direction * 0.9f), Filter = new CollisionFilter() { GroupIndex = 0, BelongsTo = 1u << 1, CollidesWith = 1u << 2 } }; return(pw.CastRay(ray)); }
protected override void OnUpdate() { float deltaTime = Time.DeltaTime; var pvs = GetComponentDataFromEntity <PhysicsVelocity>(); var pms = GetComponentDataFromEntity <PhysicsMass>(true); Entities .WithReadOnly(pms) .WithAll <Tag, AbilityCommon.Active>() .ForEach((in Owner owner, in AxisInput input, in Setting setting) => { float3 rawDirection = new float3(input.Value.x, 0, input.Value.y); if (rawDirection.Equals(0)) { return; } float3 direction = math.normalize(rawDirection); PhysicsVelocity velocity = pvs[owner.Entity]; PhysicsMass physicsMass = pms[owner.Entity]; velocity.ApplyLinearImpulse(physicsMass, setting.Strength * direction); pvs[owner.Entity] = velocity; }).Schedule();
public bool CheckRay(float3 pos, float3 targetDir, ref float3 currentDir) { if (targetDir.Equals(-currentDir)) { //don't let enemy do an abrupt 180 return(true); } var ray = new RaycastInput() { Start = pos, End = pos + (targetDir * 0.9f), Filter = new CollisionFilter() { GroupIndex = 0, BelongsTo = 1u << 1, //bitmasks, so using bitshifts CollidesWith = 1u << 2 } }; var hit = pw.CastRay(ray, out Unity.Physics.RaycastHit closestHit); return(hit); // ? math.length((closestHit.Position - pos)) : null; }