public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { bool hasTweenBuffer = chunk.Has(TweenBufferType); bool hasTargetType = chunk.Has(TargetType); NativeArray <Entity> entities = chunk.GetNativeArray(EntityType); NativeArray <TTweenCommand> commands = chunk.GetNativeArray(TweenCommandType); for (int i = 0; i < entities.Length; i++) { Entity entity = entities[i]; TTweenCommand command = commands[i]; if (!hasTweenBuffer) { ParallelWriter.AddBuffer <TweenState>(chunkIndex, entity); break; } if (!hasTargetType) { ParallelWriter.AddComponent <TTarget>(chunkIndex, entity); } TweenState tween = new TweenState(command.GetTweenParams(), ElapsedTime, chunkIndex, TweenInfoTypeIndex); ParallelWriter.AppendToBuffer(chunkIndex, entity, tween); TTweenInfo info = new TTweenInfo(); info.SetTweenId(tween.Id); info.SetTweenInfo(command.GetTweenStart(), command.GetTweenEnd()); ParallelWriter.AddComponent(chunkIndex, entity, info); ParallelWriter.RemoveComponent <TTweenCommand>(chunkIndex, entity); } }
protected override void OnUpdate() { // The command buffer to record commands, // which are executed by the command buffer system later in the frame EntityCommandBuffer.ParallelWriter commandBuffer = CommandBufferSystem.CreateCommandBuffer().AsParallelWriter(); //The DataToSpawn component tells us how many entities with buffers to create Entities.ForEach((Entity spawnEntity, int entityInQueryIndex, in DataToSpawn data) => { for (int e = 0; e < data.EntityCount; e++) { //Create a new entity for the command buffer Entity newEntity = commandBuffer.CreateEntity(entityInQueryIndex); //Create the dynamic buffer and add it to the new entity DynamicBuffer <MyBufferElement> buffer = commandBuffer.AddBuffer <MyBufferElement>(entityInQueryIndex, newEntity); //Reinterpret to plain int buffer DynamicBuffer <int> intBuffer = buffer.Reinterpret <int>(); //Optionally, populate the dynamic buffer for (int j = 0; j < data.ElementCount; j++) { intBuffer.Add(j); } } //Destroy the DataToSpawn entity since it has done its job commandBuffer.DestroyEntity(entityInQueryIndex, spawnEntity); }).ScheduleParallel(); CommandBufferSystem.AddJobHandleForProducer(this.Dependency); }
protected override void OnUpdate() { BufferFromEntity <TweenDestroyCommand> destroyBufferFromEntity = GetBufferFromEntity <TweenDestroyCommand>(true); EndSimulationEntityCommandBufferSystem endSimECBSystem = World.GetOrCreateSystem <EndSimulationEntityCommandBufferSystem>(); EntityCommandBuffer.ParallelWriter parallelWriter = endSimECBSystem.CreateCommandBuffer().AsParallelWriter(); Entities .WithReadOnly(destroyBufferFromEntity) .WithAll <TweenStopCommand>() .ForEach((int entityInQueryIndex, Entity entity, ref DynamicBuffer <TweenState> tweenBuffer) => { for (int i = 0; i < tweenBuffer.Length; i++) { TweenState tween = tweenBuffer[i]; if (!destroyBufferFromEntity.HasComponent(entity)) { parallelWriter.AddBuffer <TweenDestroyCommand>(entityInQueryIndex, entity); } parallelWriter.AppendToBuffer(entityInQueryIndex, entity, new TweenDestroyCommand(tween.Id)); } parallelWriter.RemoveComponent <TweenStopCommand>(entityInQueryIndex, entity); if (HasComponent <TweenPause>(entity)) { parallelWriter.RemoveComponent <TweenPause>(entityInQueryIndex, entity); } }).ScheduleParallel(); endSimECBSystem.AddJobHandleForProducer(Dependency); }
/// <summary> /// Use this to initialize a dynamic buffer just to temporary use other wise use AddBuffer() /// </summary> /// <param name="ecb"></param> /// <param name="addBuffer"></param> public DynamicBufferEntityBufferElement(EntityCommandBuffer.ParallelWriter ecb, int jobIndex, bool addBuffer = false) { mEntity = ecb.CreateEntity(jobIndex); if (addBuffer) { ecb.AddBuffer <EntityBufferElement>(jobIndex, mEntity); } }
public DynamicBufferColorKeyDataBufferElement(EntityCommandBuffer.ParallelWriter ecb, int jobIndex) { this.dataEntity = ecb.CreateEntity(jobIndex); this.buffer = ecb.AddBuffer <ColorKeyDataBufferElement>(jobIndex, dataEntity); this.buffer.Add(new ColorKeyDataBufferElement { Value = new ColorKeyData(float3.zero, 0) }); this.buffer.Add(new ColorKeyDataBufferElement { Value = new ColorKeyData(new float3(1f, 1f, 1f), 1) }); }
/// <summary> /// sets up the entity and buffer for entity prefab /// </summary> /// <param name="ecb"></param> /// <param name="jobIndex"></param> public static void SetupPrefabs(EntityCommandBuffer.ParallelWriter ecb, int jobIndex) { if (AllSpawnDatas.dataEntity == Entity.Null) { AllSpawnDatas.dataEntity = ecb.CreateEntity(jobIndex); AllSpawnDatas.buffer = ecb.AddBuffer <EntityPrefabBufferElement>(jobIndex, AllSpawnDatas.dataEntity); Debug.Log("Entity_Prefab: static entity and buffer is setup"); } else { Debug.LogWarning("Entity_Prefab: data are already setup."); } }
public void Execute(int index) { var chosenEntity = ChosenEntities[index]; var chosenEntityValue = IntBufferData[chosenEntity][0].Value; var chosenBoolBuffer = BoolBufferData[chosenEntity]; if (chosenBoolBuffer[0].Value) { return; } var updatedBuffer = ECB.SetBuffer <BoolData>(index, chosenEntity); updatedBuffer.Add(new BoolData { Value = true }); var generatedBuffer = ECB.AddBuffer <GeneratedEntityData>(index, chosenEntity); for (int i = 0; i < NumbersToAdd.Length; i++) { var numToAdd = NumbersToAdd[i]; var newEntity = ECB.CreateEntity(index); var intBuffer = ECB.AddBuffer <IntData>(index, newEntity); intBuffer.Add(new IntData { Value = chosenEntityValue + numToAdd }); var boolBuffer = ECB.AddBuffer <BoolData>(index, newEntity); boolBuffer.Add(new BoolData { Value = false }); generatedBuffer.Add(new GeneratedEntityData { GeneratedEntity = newEntity }); } }
protected override void OnUpdate( ) { EntityCommandBuffer.ParallelWriter ecbp = becb.CreateCommandBuffer().AsParallelWriter(); Entities.WithName("InitializePathNodeAsJob") .WithAll <PathNodeTag> () .WithNone <PathNodeElevationComponent> () .ForEach((Entity nodeEntity, int entityInQueryIndex) => { ecbp.AddComponent <PathNodeElevationComponent> (entityInQueryIndex, nodeEntity); ecbp.AddBuffer <PathNodeLinksBuffer> (entityInQueryIndex, nodeEntity); }).ScheduleParallel(); becb.AddJobHandleForProducer(Dependency); }
public DynamicBuffer <ColorKeyDataBufferElement> AddBuffer(EntityCommandBuffer.ParallelWriter ecb, int jobIndex, Entity entity) { return(ecb.AddBuffer <ColorKeyDataBufferElement>(jobIndex, entity)); }
public DynamicBufferEntityPrefab(EntityCommandBuffer.ParallelWriter ecb, int jobIndex) { dataEntity = ecb.CreateEntity(jobIndex); buffer = ecb.AddBuffer <EntityPrefabBufferElement>(jobIndex, dataEntity); }
/// <summary> /// Adds the buffer to the entity and returns the buffer /// </summary> /// <param name="ecb"></param> /// <param name="entity"></param> /// <returns></returns> public static DynamicBuffer <EntityPrefabBufferElement> AddBuffer(EntityCommandBuffer.ParallelWriter ecb, int jobIndex, Entity entity) { return(ecb.AddBuffer <EntityPrefabBufferElement>(jobIndex, entity)); }
/// <summary> /// Gets the final position of a character attempting to move from a starting /// location with a given movement. The goal of this is to move the character /// but have the character 'bounce' off of objects at angles that are /// are along the plane perpendicular to the normal of the surface hit. /// This will cancel motion through the object and instead deflect it /// into another direction giving the effect of sliding along objects /// while the character's momentum is absorbed into the wall. /// </summary> /// <param name="commandBuffer">Command buffer for adding push events to objects</param> /// <param name="jobIndex">Index of this job for command buffer use</param> /// <param name="collisionWorld">World for checking collisions and other colliable objects</param> /// <param name="start">Starting location</param> /// <param name="movement">Intended direction of movement</param> /// <param name="collider">Collider controlling the character</param> /// <param name="entityIndex">Index of this entity</param> /// <param name="rotation">Current character rotation</param> /// <param name="physicsMassAccessor">Accessor to physics mass components</param> /// <param name="anglePower">Power to raise decay of movement due to /// changes in angle between intended movement and angle of surface. /// Will be angleFactor= 1 / (1 + normAngle) where normAngle is a normalized value /// between 0-1 where 1 is max angle (90 deg) and 0 is min angle (0 degrees). /// AnglePower is the power to which the angle factor is raised /// for a sharper decline. Value of zero negates this property. /// <param name="maxBounces">Maximum number of bounces when moving. /// After this has been exceeded the bouncing will stop. By default /// this is one assuming that each move is fairly small this should approximate /// normal movement.</param> /// <param name="pushPower">Multiplier for power when pushing on an object. /// Larger values mean more pushing.</param> /// <param name="pushDecay">How much does the current push decay the remaining /// movement by. Values between [0, 1]. A zero would mean all energy is lost /// when pushing, 1 means no momentum is lost by pushing. A value of 0.5 /// would mean half of the energy is lost</param> /// <param name="epsilon">Epsilon parameter for pushing away from objects to avoid colliding /// with static objects. Should be some small float value that can be /// tuned for how much to push away while not allowing being shoved into objects.</param> /// <returns>The final location of the character.</returns> public static unsafe float3 ProjectValidMovement( EntityCommandBuffer.ParallelWriter commandBuffer, int jobIndex, CollisionWorld collisionWorld, float3 start, float3 movement, PhysicsCollider collider, int entityIndex, quaternion rotation, ComponentDataFromEntity <PhysicsMass> physicsMassGetter, float anglePower = 2, int maxBounces = 1, float pushPower = 25, float pushDecay = 0, float epsilon = 0.001f) { float3 from = start; // Starting location of movement float3 remaining = movement; // Remaining momentum int bounces = 0; // current number of bounces // Continue computing while there is momentum and bounces remaining while (math.length(remaining) > epsilon && bounces <= maxBounces) { // Get the target location given the momentum float3 target = from + remaining; // Do a cast of the collider to see if an object is hit during this // movement action var input = new ColliderCastInput() { Start = from, End = target, Collider = collider.ColliderPtr, Orientation = rotation }; SelfFilteringClosestHitCollector <ColliderCastHit> hitCollector = new SelfFilteringClosestHitCollector <ColliderCastHit>(entityIndex, 1.0f, collisionWorld); bool collisionOcurred = collisionWorld.CastCollider(input, ref hitCollector); if (!collisionOcurred && hitCollector.NumHits == 0) { // If there is no hit, target can be returned as final position return(target); } Unity.Physics.ColliderCastHit hit = hitCollector.ClosestHit; // Set the fraction of remaining movement (minus some small value) from = from + remaining * hit.Fraction; // Push slightly along normal to stop from getting caught in walls from = from + hit.SurfaceNormal * epsilon; // Apply some force to the object hit if it is moveable, Apply force on entity hit bool isKinematic = physicsMassGetter.HasComponent(hit.Entity) && IsKinematic(physicsMassGetter[hit.Entity]); if (hit.RigidBodyIndex < collisionWorld.NumDynamicBodies && !isKinematic) { commandBuffer.AddBuffer <PushForce>(jobIndex, hit.Entity); commandBuffer.AppendToBuffer(jobIndex, hit.Entity, new PushForce() { force = movement * pushPower, point = hit.Position }); // If pushing something, reduce remaining force significantly remaining *= pushDecay; } // Get angle between surface normal and remaining movement float angleBetween = math.length(math.dot(hit.SurfaceNormal, remaining)) / math.length(remaining); // Normalize angle between to be between 0 and 1 angleBetween = math.min(KCCUtils.MaxAngleShoveRadians, math.abs(angleBetween)); float normalizedAngle = angleBetween / KCCUtils.MaxAngleShoveRadians; // Create angle factor using 1 / (1 + normalizedAngle) float angleFactor = 1.0f / (1.0f + normalizedAngle); // If the character hit something // Reduce the momentum by the remaining movement that ocurred remaining *= (1 - hit.Fraction) * math.pow(angleFactor, anglePower); // Rotate the remaining remaining movement to be projected along the plane // of the surface hit (emulate pushing against the object) // A is our vector and B is normal of plane // A || B = B × (A×B / |B|) / |B| // From http://www.euclideanspace.com/maths/geometry/elements/plane/lineOnPlane/index.htm float3 planeNormal = hit.SurfaceNormal; float momentumLeft = math.length(remaining); remaining = math.cross(planeNormal, math.cross(remaining, planeNormal) / math.length(planeNormal)) / math.length(planeNormal); remaining = math.normalizesafe(remaining) * momentumLeft; // Track number of times the character has bounced bounces++; } return(from); }
/// <summary> /// Adds the buffer to the entity and returns the buffer /// </summary> /// <param name="ecb"></param> /// <param name="entity"></param> /// <returns></returns> public static DynamicBuffer <ProceduralGenerationSpawnDataBufferElement> AddBuffer(EntityCommandBuffer.ParallelWriter ecb, int indexJob, Entity entity) { return(ecb.AddBuffer <ProceduralGenerationSpawnDataBufferElement>(indexJob, entity)); }
public DynamicBuffer <T> AddBuffer <T>() where T : struct, IBufferElementData { return(_ecb.AddBuffer <T>(_jobIndex, _entity)); }
public void Execute(Entity entity, int jobIndex, [ReadOnly] ref NetworkStreamConnection con) { var rpcBuffer = commandBuffer.AddBuffer <OutgoingRpcDataStreamBufferComponent>(jobIndex, entity); RpcSystem.SendProtocolVersion(rpcBuffer, protocolVersion); }
protected override void OnUpdate() { BufferFromEntity <TweenDestroyCommand> destroyBufferFromEntity = GetBufferFromEntity <TweenDestroyCommand>(true); EndSimulationEntityCommandBufferSystem endSimECBSystem = World.GetOrCreateSystem <EndSimulationEntityCommandBufferSystem>(); EntityCommandBuffer.ParallelWriter parallelWriter = endSimECBSystem.CreateCommandBuffer().AsParallelWriter(); Entities .WithReadOnly(destroyBufferFromEntity) .WithNone <TweenPause>() .ForEach((Entity entity, int entityInQueryIndex, ref DynamicBuffer <TweenState> tweenBuffer) => { for (int i = tweenBuffer.Length - 1; i >= 0; i--) { TweenState tween = tweenBuffer[i]; bool isInfiniteLoop = tween.LoopCount == TweenState.LOOP_COUNT_INFINITE; float normalizedTime = tween.GetNormalizedTime(); if (tween.IsReverting && normalizedTime <= 0.0f) { if (!isInfiniteLoop) { tween.LoopCount--; } tween.IsReverting = false; tween.Time = 0.0f; } else if (!tween.IsReverting && normalizedTime >= 1.0f) { if (tween.IsPingPong) { tween.IsReverting = true; tween.Time = tween.Duration / 2.0f; } else { if (!isInfiniteLoop) { tween.LoopCount--; } tween.Time = 0.0f; } } if (!isInfiniteLoop && tween.LoopCount == 0) { if (!destroyBufferFromEntity.HasComponent(entity)) { parallelWriter.AddBuffer <TweenDestroyCommand>(entityInQueryIndex, entity); } parallelWriter.AppendToBuffer(entityInQueryIndex, entity, new TweenDestroyCommand(tween.Id)); } tweenBuffer[i] = tween; } }).ScheduleParallel(); endSimECBSystem.AddJobHandleForProducer(Dependency); }