protected override void OnUpdate() { // stores amount of queried entities int dataCount = query.CalculateEntityCount(); // concurrent command buffer for use in parralel jobs LayerMask walls = 1 << 6; Vector3 playerPosition = new Vector3(); Entities.ForEach((ref PlayerInputButtons buttons, ref Translation trans) => { playerPosition = (Vector3)trans.Value; }).Run(); // Allocating native arrays to store data inbetween jobs NativeArray <UnityEngine.RaycastHit> results = new NativeArray <UnityEngine.RaycastHit>(dataCount, Allocator.TempJob); NativeArray <RaycastCommand> rayCastCommand = new NativeArray <RaycastCommand>(dataCount, Allocator.TempJob); NativeArray <bool> hits = new NativeArray <bool>(dataCount, Allocator.TempJob); // building raycast commands based on selected entities JobHandle jobHandle = Entities.WithStoreEntityQueryInField(ref query) .ForEach((Entity entity, int entityInQueryIndex, in NPCTag npc, in Translation trans) => { Vector3 origin = (Vector3)trans.Value; Vector3 direction = playerPosition - origin; rayCastCommand[entityInQueryIndex] = new RaycastCommand(origin, direction, npc.range, walls); }).ScheduleParallel(Dependency);
public void Execute() { for (int i = 0; i < raycastCommands.Length; i++) { raycastCommands[i] = new RaycastCommand(origins[i] + originOffset, direction, distance, mask, 1); } }
// Update is called once per frame void Update() { var commands = new NativeArray <RaycastCommand>(targets.Length, Allocator.TempJob); var results = new NativeArray <RaycastHit>(targets.Length, Allocator.Temp); for (int i = 0; i < targets.Length; i++) { var targetPosition = targets[i].position; var direction = Vector3.down; var command = new RaycastCommand(targetPosition, direction); commands[i] = command; } RaycastCommand.ScheduleBatch(commands, results, 20).Complete(); commands.Dispose(); for (int i = 0; i < targets.Length; i++) { Debug.Log(velocity.Length); if (velocity[i] < 0 && results[i].distance < 0.5f) { velocity[i] = 1; } velocity[i] -= 0.098f; } results.Dispose(); for (int i = 0; i < targets.Length; i++) { targets[i].localPosition += Vector3.up * velocity[i]; } }
// root = the bottom left most sector. public void SetAdjacentNodes(int2 root) { s_SetAdjacentNodes.Begin(); float3 centerOffset = new float3(root.x * m_GridSpacing, root.y * m_GridSpacing, 0.0f) - new float3(m_GridDimensions * m_GridSpacing, m_GridDimensions * m_GridSpacing, 0.0f); for (int y = 0, index = 0; y < m_RootNodeDimension; y++) { for (int x = 0; x < m_RootNodeDimension; x++, index++) { m_RaycastCommands[index] = new RaycastCommand(centerOffset + new float3(x * m_SectorSpacing, y * m_SectorSpacing, -1.0f), Vector3.forward, 1.5f, m_ParentLayer, 1); } } RaycastCommand.ScheduleBatch(m_RaycastCommands, m_RootNodeHits, 8).Complete(); for (int y = 0, index = 0; y < m_RootNodeDimension; y++) { for (int x = 0; x < m_RootNodeDimension; x++, index++) { colliderArray[index] = (m_RootNodeHits[index].collider != null) ? m_RootNodeHits[index].collider.GetComponent <GravNodeCollider>() : null; parentGridPoses[index] = (colliderArray[index] != null) ? colliderArray[index].GetNodeTransform() : centerOffset + new float3(x * m_SectorSpacing, y * m_SectorSpacing, 0.0f); } } s_SetAdjacentNodes.End(); }
private void CastRaysJob() { NativeArray <RaycastHit> results = new NativeArray <RaycastHit>(rayAmount, Allocator.TempJob); NativeArray <RaycastCommand> commands = new NativeArray <RaycastCommand>(rayAmount, Allocator.TempJob); for (int i = 0; i < rayAmount; i++) { Ray r = cam.ViewportPointToRay(new Vector3(rPoints[i].x, rPoints[i].y, 0f)); commands[i] = new RaycastCommand(r.origin, r.direction, rayDistance); } var handle = RaycastCommand.ScheduleBatch(commands, results, 1); handle.Complete(); for (int i = 0; i < results.Length; i++) { RaycastHit batchedHit = results[i]; if (batchedHit.collider == null) { continue; } batchedHit.transform.GetComponent <OcclusionObject>()?.HitOcclude(stayTime); } commands.Dispose(); results.Dispose(); }
public void Execute(Entity entity, int index, ref Translation translation, ref MobTargetPos mobTargetPos) { float3 shootTarget = new float3(mobTargetPos.Value.x, wallPos.y, mobTargetPos.Value.z); float3 dir = shootTarget - translation.Value; rayCommands[index] = new RaycastCommand(translation.Value, dir, SettingsManager.ShootingRange, layerMask); }
public void NeedForMinStepTest(bool shouldFail) { var maxHits = 4; var rayStart = new Vector3(0f, 4f, 0f); var meshConvexCommand = new RaycastCommand(meshConvexCollider.transform.position + rayStart, Vector3.down, 8f); var commandsArray = new RaycastCommand[] { meshConvexCommand }; var commands = new NativeArray <RaycastCommand>(commandsArray, Allocator.TempJob); var commandHits = new NativeArray <RaycastHit>(commands.Length * maxHits, Allocator.TempJob); //setting minStep to 0f var raycastAllCommand = new RaycastAllCommand(commands, commandHits, maxHits, shouldFail ? 0f : 0.0001f); raycastAllCommand.Schedule(default(JobHandle)).Complete(); Assert.AreEqual(meshConvexCollider, commandHits[0].collider); var collider = commandHits[1].collider; if (shouldFail) { Assert.IsNotNull(collider, "RaycastHit in corner point behaviour changed, minStep may be no longer required"); } else { Assert.IsNull(collider); } commandHits.Dispose(); commands.Dispose(); raycastAllCommand.Dispose(); }
private JobHandle JobChain(JobHandle inputDeps) { var size = data.Length * data.checks[0].values.Length * 2; // Build the RaycastCommands var commands = new NativeArray <RaycastCommand>(size, Allocator.TempJob); // Output var results = new NativeArray <RaycastHit>(size, Allocator.TempJob); var raycastJob = new RaycastSetUp { checkpoints = data.checks, commands = commands }; var deps = raycastJob.Schedule(inputDeps); deps.Complete(); // Do the raycast job deps = RaycastCommand.ScheduleBatch(commands, results, 32, inputDeps); deps.Complete(); UpdatePlayerLap(results); // Dispose the raycast commands as the results are needed. commands.Dispose(); // Dispose the results, we've finished processing them. results.Dispose(); return(deps); }
void DoReadyShots(int count, ref List <RaycastHit> hits, ref JobHandle handle) { try { // Create arrays for shot rays and results with variable size shotRays = new NativeArray <RaycastCommand>(count, Allocator.TempJob); shotResults = new NativeArray <RaycastHit>(count, Allocator.TempJob); // Get all ready shot rays for (int i = 0; i < count; i++) { shotRays[i] = allShots[readyShotsIndex[i]].ray; } // Schedule raycast job handle = RaycastCommand.ScheduleBatch(shotRays, shotResults, count, default(JobHandle)); // Confirm completion of job handle.Complete(); // Immediately send results to a proper list hits = shotResults.ToList(); // Dispose of temporary arrays shotRays.Dispose(); shotResults.Dispose(); } catch (InvalidOperationException e) { Debug.LogWarning("[CaughtError] Error in DoReadyShots: " + e.ToString()); } }
public void Execute(int index) { vec3 rd = Samples[index]; vec3 ro = RayOrigin; Raycasts[index] = new RaycastCommand(ro, rd, RayLengths[index], LayerMask); }
void IJobParallelForTransform.Execute(int i, TransformAccess t) { BulletData data = BulletData[i]; data.PositionOld = data.Position; Vector3 delta = Vector3.zero; switch (BulletData[i].Type) { case BulletType.Dummy: if (Time - data.StartTime > 2.0f) { data.ToBeKilled = true; break; } data.Velocity += new Vector3(0, 0, 0) * DeltaTime; delta = data.Velocity * DeltaTime; data.Position += delta; break; } Vector3 direction = data.Velocity.normalized; t.position = data.Position; t.rotation = Quaternion.LookRotation(direction); BulletData[i] = data; RaycastCommands[i] = new RaycastCommand(data.PositionOld, direction, delta.magnitude, LayerMask); }
public void Execute(int index, TransformAccess transform) { Vector3 shootTarget = new Vector3(targetPos[index].x, wallPos.y, targetPos[index].z); Vector3 dir = shootTarget - transform.position; rayCommands[index] = new RaycastCommand(transform.position, dir, SettingsManager.ShootingRange, layerMask); }
public void Execute() { var cmdIdx = 0; for (var i = startIdx; i < endIdx; ++i) { if (positionHasColliders[i]) { var position = positions[i]; var searchDistance = searchDistanceForPosition[i]; for (var j = 0; j < kRayDirectionsPerPosition; ++j) { var direction = kRayDirections[j]; var origin = position + direction * voSettings.rayOriginBias; raycastCommands[cmdIdx++] = new RaycastCommand(origin, direction, searchDistance, voSettings.collisionMask, voSettings.maxHitsPerRay); } } else { // Since there's no option to dispatch commands with a subset of an array, we fill up the commands buffer with no-op raycasts. for (var j = 0; j < kRayDirectionsPerPosition; ++j) { raycastCommands[cmdIdx++] = new RaycastCommand(Vector3.zero, Vector3.zero, 0f, 0, voSettings.maxHitsPerRay); } } } // Zero out any remainder of the raycast array for (; cmdIdx < raycastCommands.Length;) { raycastCommands[cmdIdx++] = new RaycastCommand(Vector3.zero, Vector3.zero, 0f, 0, voSettings.maxHitsPerRay); } }
/// <summary> /// 该接口要达到一定量级性能才会更优 /// </summary> /// <param name="bounds"></param> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> public static RaycastHit[] RaycastGrid(Vector3 center, int width, int height, int layerMask = -1, int maxHists = 1, int maxHeight = 1000) { var results = new NativeArray <RaycastHit>(width * height * maxHists, Allocator.TempJob); var commands = new NativeArray <RaycastCommand>(width * height, Allocator.TempJob); var halfWidth = (width - 1) * 0.5f; var halfHeight = (height - 1) * 0.5f; var offsetHeight = Vector3.up * maxHeight; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { var rayCenter = center - new Vector3(halfWidth, center.y, halfHeight) + new Vector3(i, 0, j); commands[i + j * width] = new RaycastCommand(rayCenter + offsetHeight, Vector3.down, layerMask: layerMask); } } if (maxHists == 1) { var handle = RaycastCommand.ScheduleBatch(commands, results, 1); handle.Complete(); } else { var handle = new RaycastAllCommand(commands, results, maxHists); handle.Schedule(default).Complete();
void Update() { handle.Complete(); // Raycastの開始点と位置を設定 for (int i = 0; i < transformArray.length; i++) { var targetPosition = transformArray[i].position; var direction = Vector3.down; var command = new RaycastCommand(targetPosition, direction); commands[i] = command; } // 移動のコマンドを設定 UpdatePosition updatePositionJob = new UpdatePosition() { raycastResults = results, velocitys = velocity }; ApplyPosition applyPosition = new ApplyPosition() { velocitys = velocity }; // 並列処理を実行(即完了待ち) // 終わったらコマンドに使ったバッファは不要なので破棄 var raycastJobHandle = RaycastCommand.ScheduleBatch(commands, results, 20); var updatePositionHandle = updatePositionJob.Schedule(transformArray.length, 20, raycastJobHandle); handle = applyPosition.Schedule(transformArray, updatePositionHandle); JobHandle.ScheduleBatchedJobs(); }
// Update is called once per frame void Update() { handle.Complete(); for (int i = 0; i < targets.Length; i++) { var targetPosition = targets[i].position; var direction = Vector3.down; var command = new RaycastCommand(targetPosition, direction); commands[i] = command; } // 移動的command 設定 UpdatePosition updatePositionJob = new UpdatePosition() { raycastResults = results, objVelocitys = velocities }; ApplyPosition applyPosition = new ApplyPosition() { objVelocitys = velocities }; var raycastJobHandle = RaycastCommand.ScheduleBatch(commands, results, 20); var updatePositionHandle = updatePositionJob.Schedule(transformArray.length, 20, raycastJobHandle); handle = applyPosition.Schedule(transformArray, updatePositionHandle); }
private void RaycasExample() { // Perform a single raycast using RaycastCommand and wait for it to complete // Setup the command and result buffers var results = new NativeArray <RaycastHit>(1, Allocator.Temp); var commands = new NativeArray <RaycastCommand>(1, Allocator.Temp); // Set the data of the first command Vector3 origin = Vector3.forward * -10; Vector3 direction = Vector3.forward; commands[0] = new RaycastCommand(origin, direction); // Schedule the batch of raycasts JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); // Wait for the batch processing job to complete handle.Complete(); // Copy the result. If batchedHit.collider is null there was no hit RaycastHit batchedHit = results[0]; // Dispose the buffers results.Dispose(); commands.Dispose(); }
public static void BakeObject(GameObject obj, float rayLength, bool stochastic = false, int sampleCount = 8) { float startTime = Time.realtimeSinceStartup; Mesh mesh = obj.GetComponent <MeshFilter>().sharedMesh; List <Vector3> vert = new List <Vector3>(); mesh.GetVertices(vert); List <Vector3> norm = new List <Vector3>(); mesh.GetNormals(norm); Color[] colors = new Color[vert.Count]; for (int r = 0; r < sampleCount; r++) { var results = new NativeArray <RaycastHit>(mesh.vertexCount, Allocator.TempJob); var commands = new NativeArray <RaycastCommand>(mesh.vertexCount, Allocator.TempJob); for (int i = 0; i < mesh.vertexCount; i++) { Vector3 randomVectors = new Vector3(Random.Range(-1, 1), Random.Range(-1, 1), Random.Range(-1, 1)) * 0.3f; if (!stochastic) { randomVectors = Vector3.zero; } commands[i] = new RaycastCommand(obj.transform.localToWorldMatrix.MultiplyPoint(vert[i]) + obj.transform.localToWorldMatrix.MultiplyVector(norm[i]) * 0.002f, obj.transform.localToWorldMatrix.MultiplyVector(norm[i]) + randomVectors, rayLength); } JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); for (int i = 0; i < results.Length; i++) { if (results[i].collider != null) { RaycastHit hit = results[i]; if (!isPointLit(hit.point + hit.normal * 0.01f)) { colors[i] += fromValue(Mathf.Clamp01(hit.distance / rayLength)) / sampleCount; } else { colors[i] += Color.white / sampleCount; } } else { colors[i] += Color.white / sampleCount; } } commands.Dispose(); results.Dispose(); } if (useDebug) { Debug.Log("Baked object " + obj.name + " in " + (Time.realtimeSinceStartup - startTime) + "ms"); } mesh.SetColors(colors); }
/* * Might cause memory leaks if interrupted before NativeArrays are disposed */ private static void ParallelIncrementalRaycast( List <ParallelIncrementalRaycastData> paths ) { List <ParallelIncrementalRaycastData> remainingPaths = new List <ParallelIncrementalRaycastData>(paths); NativeArray <RaycastHit> results = default(NativeArray <RaycastHit>); NativeArray <RaycastCommand> commands = default(NativeArray <RaycastCommand>); do { results = new NativeArray <RaycastHit>(remainingPaths.Count, Allocator.TempJob); commands = new NativeArray <RaycastCommand>(remainingPaths.Count, Allocator.TempJob); for (int i = 0; i < remainingPaths.Count; i++) { commands[i] = new RaycastCommand( remainingPaths[i].start, remainingPaths[i].dx, remainingPaths[i].remaining.magnitude, instance.collisionMask ); } JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); for (int i = 0; i < remainingPaths.Count; i++) { ParallelIncrementalRaycastData data = remainingPaths[i]; RaycastHit batchedHit = results[i]; data.hit = batchedHit; if (batchedHit.collider == null) { continue; } data.remaining -= (batchedHit.point - data.start); data.start = (batchedHit.point + data.dx); if (batchedHit.collider.transform.GetComponent <Obstacle>() != null) { IntersectionResult result = new IntersectionResult(batchedHit); data.onIntersect(result); } } remainingPaths.RemoveAll( path => !path.continueCondition(path.result) || path.hit.collider == null ); results.Dispose(); commands.Dispose(); } while (remainingPaths.Count > 0); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (minionSystem == null) { return(inputDeps); } if (arrows.Length == 0) { return(inputDeps); } if (minions.Length == 0) { return(inputDeps); } // Update seems to be called after Play mode has been exited // ============ REALLOC =============== // todo fix nativearray NativeArrayExtensions.ResizeNativeArray(ref raycastHits, math.max(raycastHits.Length, arrows.Length)); NativeArrayExtensions.ResizeNativeArray(ref raycastCommands, math.max(raycastCommands.Length, arrows.Length)); // ============ JOB CREATION =============== var arrowJob = new ProgressArrowJob { raycastCommands = raycastCommands, arrows = arrows.data, arrowEntities = arrows.entities, dt = Time.deltaTime, allMinionTransforms = minions.transforms, buckets = minionSystem.CollisionBuckets, minionConstData = minions.constData, AttackCommands = CommandSystem.AttackCommandsConcurrent, minionEntities = minions.entities, queueForKillingEntities = lifecycleManager.queueForKillingEntities }; var stopArrowJob = new StopArrowsJob { raycastHits = raycastHits, arrows = arrows.data, arrowEntities = arrows.entities, stoppedArrowsQueue = lifecycleManager.deathQueue }; var arrowJobFence = arrowJob.Schedule(arrows.Length, SimulationState.SmallBatchSize, JobHandle.CombineDependencies(inputDeps, CommandSystem.AttackCommandsFence)); arrowJobFence.Complete(); var raycastJobFence = RaycastCommand.ScheduleBatch(raycastCommands, raycastHits, SimulationState.SmallBatchSize, arrowJobFence); var stopArrowJobFence = stopArrowJob.Schedule(arrows.Length, SimulationState.SmallBatchSize, raycastJobFence); CommandSystem.AttackCommandsConcurrentFence = JobHandle.CombineDependencies(stopArrowJobFence, CommandSystem.AttackCommandsConcurrentFence); // Complete arrow movement return(stopArrowJobFence); }
public void Execute(int i) { preCollisionVerts[i] = bodyVerts[i]; Vector3 rayOrigin = prevBodyVerts[i] - (bodyNormals[i] * penetrationDepth); Vector3 rayDir = (bodyVerts[i] - rayOrigin); float rayMagnitude = rayDir.magnitude; raycasts[i] = new RaycastCommand(rayOrigin, rayDir / rayMagnitude, rayMagnitude); //bodyNormals[i] }
public void Execute(int index) { int i_obs = Mathf.FloorToInt(index / MPC_Array.Length); int i_mpc = index - i_obs * MPC_Array.Length; Vector3 temp_direction = MPC_Array[i_mpc].Coordinates - OBS_Array[i_obs]; commands[index] = new RaycastCommand(OBS_Array[i_obs], temp_direction.normalized, temp_direction.magnitude); }
public void Execute(int i) { // figure out how far the object we are testing collision for // wants to move in total. Our collision raycast only needs to be // that far. float distance = (Velocities[i] * DeltaTime).magnitude; Raycasts[i] = new RaycastCommand(Positions[i], Velocities[i], distance); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { RocketRotateJob rocketRotateJob = new RocketRotateJob { vec3CometPosition = GameManager.instance.Comet.position, }; JobHandle rotateHandle = rocketRotateJob.Schedule(this, inputDeps); if (m_raycastJH.IsCompleted) { World.Active.GetOrCreateManager <SpaceShipMoveSystem>().m_spaceShipOffsetMoveJH.Complete(); for (int i = 0; i < m_rocketProximityGroup.Length; ++i) { float DistBetweenCenters = Vector3.Distance(GameManager.instance.Comet.position, m_rocketProximityGroup.Positions[i].Value); if (DistBetweenCenters < GameManager.instance.CometColliderRadius * 2 + m_rocketProximityGroup.Collisions[i].Height) { m_entityManager.SetComponentData(m_rocketProximityGroup.Entities[i], new RocketProximityState { Value = 2 }); } else if (i < m_raycastHits.Length - 1 && m_raycastHits[i].collider != null) { m_entityManager.SetComponentData(m_rocketProximityGroup.Entities[i], new RocketProximityState { Value = 1 }); } else { m_entityManager.SetComponentData(m_rocketProximityGroup.Entities[i], new RocketProximityState { Value = 0 }); } } m_raycastHits.Dispose(); m_raycastCommands.Dispose(); int opSize = m_rocketProximityGroup.Length; m_raycastCommands = new NativeArray <RaycastCommand>(opSize, Allocator.Persistent); m_raycastHits = new NativeArray <RaycastHit>(opSize, Allocator.Persistent); for (int i = 0; i < opSize; ++i) { Vector3 pos = m_rocketProximityGroup.Positions[i].Value; Vector3 dir = GameManager.instance.Comet.position - pos; m_raycastCommands[i] = new RaycastCommand(pos, dir.normalized, raycastLength, cometRaycastMask); } m_raycastJH = RaycastCommand.ScheduleBatch(m_raycastCommands, m_raycastHits, GameManager.SubJobsSplit, rotateHandle); } return(JobHandle.CombineDependencies(rotateHandle, m_raycastJH)); }
// Build a job chain with a given scanner. JobHandle BuildJobChain(float3 origin, Scanner scanner, JobHandle deps) { // Transform output destination var transforms = _voxelGroup.GetComponentDataArray <LocalToWorld>(); if (transforms.Length == 0) { return(deps); } if (_pTransformCount == null) { // Initialize the transform counter. _pTransformCount = (int *)UnsafeUtility.Malloc( sizeof(int), sizeof(int), Allocator.Persistent); *_pTransformCount = 0; } else { // Wrap around the transform counter to avoid overlfow. *_pTransformCount %= transforms.Length; } // Total count of rays var total = scanner.Resolution.x * scanner.Resolution.y; // Ray cast command/result array var commands = new NativeArray <RaycastCommand>(total, Allocator.TempJob); var hits = new NativeArray <RaycastHit>(total, Allocator.TempJob); // 1: Set-up jobs var setupJob = new SetupJob { Commands = commands, Origin = origin, Extent = scanner.Extent, Resolution = scanner.Resolution }; deps = setupJob.Schedule(total, 64, deps); // 2: Raycast jobs deps = RaycastCommand.ScheduleBatch(commands, hits, 16, deps); // 3: Transfer jobs var transferJob = new TransferJob { RaycastCommands = commands, RaycastHits = hits, Scale = scanner.Extent.x * 2 / scanner.Resolution.x, Transforms = transforms, pCounter = _pTransformCount }; deps = transferJob.Schedule(total, 64, deps); return(deps); }
public void Schedule(int minCommandsPerJob = 32, JobHandle dependsOn = default(JobHandle)) { #if DEBUG if (_handle.IsCompleted == false) { Debug.LogWarning("Scheduling when job is not complete"); } #endif this._handle = RaycastCommand.ScheduleBatch(this.commands, this.results, minCommandsPerJob, dependsOn); }
public void Execute(int index) { var directionIndex = index % Directions.Length; var positionIndex = index % Origins.Length; var position = Origins[positionIndex]; Commands[index] = new RaycastCommand { from = position, distance = MaximumDistance, layerMask = LayerMask, direction = Directions[directionIndex], maxHits = 1 }; }
public void Schedule(int minCommandsPerJob = 32, JobHandle dependsOn = default(JobHandle)) { #if DEBUG if (_raycastBatchJobHandle.IsCompleted == false) { Debug.LogWarning("WARNING: Scheduling when job is not complete"); } #endif _raycastBatchJobHandle = RaycastCommand.ScheduleBatch(_raycastCommands, _raycastHitresults, minCommandsPerJob, dependsOn); }
public void Execute(int index) { commands[index] = new RaycastCommand { from = prevPositions[index].Value, direction = math.forward(rotations[index].Value), distance = math.distance(positions[index].Value, prevPositions[index].Value), layerMask = hitLayer, maxHits = math.clamp(multiHits[index].MaxHits - multiHits[index].Hits, 0, multiHits[index].MaxHits) }; }
public void Execute(int index) { cmds[index] = new RaycastCommand { from = prevPositions[index].Value, direction = math.forward(rotations[index].Value), distance = math.distance(prevPositions[index].Value, curPositions[index].Value), layerMask = hitMask, maxHits = 1 }; }