Exemplo n.º 1
0
 // Use this for initialization
 void Start()
 {
     gameObject.SetActive(false);
     ComponentLocator.instance.GetDependency <PlayerIdentifierComponent>().playerGameObject.GetComponent <HealthComponent>().dieEvent += GameOver;
     playerScoreComponent = ComponentLocator.instance.GetDependency <PlayerScoreComponent>();
     ComponentLocator.instance.GetDependency <PlayerIdentifierComponent>().GetComponent <PlayerReviveComponent>().playerRevivedEvent += playerRevived;
     aISpawnComponent = ComponentLocator.instance.GetDependency <AISpawnComponent>();
 }
    protected override void OnUpdate()
    {
        //Here we set the prefab we will use
        if (m_Prefab == Entity.Null)
        {
            //We grab the converted PrefabCollection Entity's PlayerScoreAuthoringComponent
            //and set m_Prefab to its Prefab value
            m_Prefab = GetSingleton <PlayerScoreAuthoringComponent>().Prefab;
            //We then initialize by creating the first PlayerScore
            var initialPlayerScore = EntityManager.Instantiate(m_Prefab);
            //We set the initial player score to 1 so the first player will be assigned this PlayerScore
            EntityManager.SetComponentData <PlayerScoreComponent>(initialPlayerScore, new PlayerScoreComponent {
                networkId = 1
            });
            //we must "return" after setting this prefab because if we were to continue into the Job
            //we would run into errors because the variable was JUST set (ECS funny business)
            //comment out return and see the error
            return;
        }

        //We need to declare our local variables before the .ForEach()
        var commandBuffer = m_BeginSimEcb.CreateCommandBuffer();
        //We use this to check for disconnects
        var rpcFromEntity = GetBufferFromEntity <OutgoingRpcDataStreamBufferComponent>();
        //We are going to grab all existing player scores because we need to check if the new player has an old NetworkId
        var currentPlayerScoreEntities = m_PlayerScoresQuery.ToEntityArray(Allocator.TempJob);
        //We are going to need to grab the Player score from the entity
        var playerScoreComponent = GetComponentDataFromEntity <PlayerScoreComponent>();
        //We grab the prefab in case we need to create a new PlayerScore for a new NetworkId
        var scorePrefab = m_Prefab;
        //We are going to need to be able to grab the NetworkIdComponent from the RPC source to know what the player's NetworkId is
        var networkIdFromEntity = GetComponentDataFromEntity <NetworkIdComponent>();

        Entities
        .WithDisposeOnCompletion(currentPlayerScoreEntities)
        .ForEach((Entity entity, in SendServerPlayerNameRpc request, in ReceiveRpcCommandRequestComponent requestSource) =>
        {
            //Delete the rpc
            commandBuffer.DestroyEntity(entity);

            //Check for disconnects
            if (!rpcFromEntity.HasComponent(requestSource.SourceConnection))
            {
                return;
            }

            //Grab the NetworkIdComponent's Value
            var newPlayersNetworkId = networkIdFromEntity[requestSource.SourceConnection].Value;

            //We create a clean PlayerScore component with the player's name and the player's NetworkId value
            var newPlayerScore = new PlayerScoreComponent {
                networkId    = newPlayersNetworkId,
                playerName   = request.playerName,
                currentScore = 0,
                highScore    = 0
            };

            //Now we are going to check all current PlayerScores and see if this NetworkId has been used before
            //If it has we set it to our new PlayerScoreComponent
            bool uniqueNetworkId = true;
            for (int i = 0; i < currentPlayerScoreEntities.Length; i++)
            {
                //We call the data componentData just to make it more legible on the if() line
                var componentData = playerScoreComponent[currentPlayerScoreEntities[i]];
                if (componentData.networkId == newPlayersNetworkId)
                {
                    commandBuffer.SetComponent <PlayerScoreComponent>(currentPlayerScoreEntities[i], newPlayerScore);
                    uniqueNetworkId = false;
                }
            }
            //If this NetworkId has not been used before we create a new PlayerScore
            if (uniqueNetworkId)
            {
                var playerScoreEntity = commandBuffer.Instantiate(scorePrefab);
                //We set the initial player score to 1 so the first player will be assigned this PlayerScore
                commandBuffer.SetComponent <PlayerScoreComponent>(playerScoreEntity, newPlayerScore);
            }
        }).Schedule();
Exemplo n.º 3
0
    protected override void OnUpdate()
    {
        // Need this extra variable here so that it can
        // be captured by Entities.ForEach loop below
        var nonTriggerMask = m_NonTriggerMask;

        //We grab all the player scores because we don't know who will need to be assigned points
        var playerScoreEntities = m_PlayerScores.ToEntityArray(Allocator.TempJob);
        //we will need to grab the PlayerScoreComponent from our player score entities to compare values
        var playerScoreComponent = GetComponentDataFromEntity <PlayerScoreComponent>();

        //We grab the 1 HighestScore engity
        var highestScoreEntities = m_HighestScore.ToEntityArray(Allocator.TempJob);
        //We will need to grab the HighestScoreComponent from our highest score entity to compare values
        var highestScoreComponent = GetComponentDataFromEntity <HighestScoreComponent>();

        //We are going to use this to pull the GhostOwnerComponent from the bullets to see who they belong to
        var ghostOwner = GetComponentDataFromEntity <GhostOwnerComponent>();

        //We need to dispose our entities
        Entities
        .WithDisposeOnCompletion(playerScoreEntities)
        .WithDisposeOnCompletion(highestScoreEntities)
        .WithName("ChangeMaterialOnTriggerEnter")
        .ForEach((Entity e, ref DynamicBuffer <StatefulTriggerEvent> triggerEventBuffer) =>
        {
            for (int i = 0; i < triggerEventBuffer.Length; i++)
            {
                //Here we grab our bullet entity and the other entity it collided with
                var triggerEvent = triggerEventBuffer[i];
                var otherEntity  = triggerEvent.GetOtherEntity(e);

                // exclude other triggers and processed events
                if (triggerEvent.State == EventOverlapState.Stay || !nonTriggerMask.Matches(otherEntity))
                {
                    continue;
                }

                //We want our code to run on the first intersection of Bullet and other entity
                else if (triggerEvent.State == EventOverlapState.Enter)
                {
                    //We grab the NetworkId of the bullet so we know who to assign points to
                    var bulletsPlayerNetworkId = ghostOwner[e].NetworkId;

                    //We start with 0 points to add
                    int pointsToAdd = 0;
                    if (HasComponent <PlayerTag>(otherEntity))
                    {
                        //Now we check if the bullet came from the same player
                        if (ghostOwner[otherEntity].NetworkId == bulletsPlayerNetworkId)
                        {
                            //If it is from the same player no points
                            return;
                        }
                        pointsToAdd += 10;
                    }

                    if (HasComponent <AsteroidTag>(otherEntity))
                    {
                        //Bullet hitting an Asteroid is 1 point
                        pointsToAdd += 1;
                    }

                    //After updating the points to add we check the PlayerScore entities and find the one with the
                    //correct NetworkId so we can update the scores for the PlayerScoreComponent
                    //If the updated score is higher than the highest score it updates the highest score
                    for (int j = 0; j < playerScoreEntities.Length; j++)
                    {
                        //Grab the PlayerScore
                        var currentPlayScoreComponent = playerScoreComponent[playerScoreEntities[j]];
                        if (currentPlayScoreComponent.networkId == bulletsPlayerNetworkId)
                        {
                            //We create a new component with updated values
                            var newPlayerScore = new PlayerScoreComponent {
                                networkId    = currentPlayScoreComponent.networkId,
                                playerName   = currentPlayScoreComponent.playerName,
                                currentScore = currentPlayScoreComponent.currentScore + pointsToAdd,
                                highScore    = currentPlayScoreComponent.highScore
                            };
                            //Here we check if the player beat their own high score
                            if (newPlayerScore.currentScore > newPlayerScore.highScore)
                            {
                                newPlayerScore.highScore = newPlayerScore.currentScore;
                            }

                            //Here we check if the player beat the highest score
                            var currentHighScore = highestScoreComponent[highestScoreEntities[0]];
                            if (newPlayerScore.highScore > currentHighScore.highestScore)
                            {
                                //If it does we make a new HighestScoreComponent
                                var updatedHighestScore = new HighestScoreComponent {
                                    highestScore = newPlayerScore.highScore,
                                    playerName   = newPlayerScore.playerName
                                };

                                //The reason why we don't go with:
                                //SetComponent<HighestScoreComponent>(highestScoreEntities[0],  updatedHighestScore);
                                //is because SetComponent<HighestScoreComponent>() gets codegen'd into ComponentDataFromEntity<HighestScoreComponent>()
                                //and you can't use 2 different ones or else you get an 'two containers may not be the same (aliasing)' error
                                highestScoreComponent[highestScoreEntities[0]] = updatedHighestScore;
                            }
                            // SetComponent<PlayerScoreComponent>(playerScoreEntities[j], newPlayerScore);
                            //The reason why we don't go with:
                            //SetComponent<PlayerScoreComponent>(playerScoreEntities[j],  newPlayerScore);
                            //is because SetComponent<PlayerScoreComponent>() gets codegen'd into ComponentDataFromEntity<PlayerScoreComponent>()
                            //and you can't use 2 different ones or else you get an 'two containers may not be the same (aliasing)' error
                            playerScoreComponent[playerScoreEntities[j]] = newPlayerScore;
                        }
                    }
                }
                else
                {
                    continue;
                }
            }
        }).Schedule();
    }
    protected override void OnUpdate()
    {
        //We add "AsParallelWriter" when we create our command buffer because we want
        //to run our jobs in parallel
        var commandBuffer = m_EndSimEcb.CreateCommandBuffer().AsParallelWriter();

        //We are going to need to update the NCE CommandTargetComponent so we set the argument to false (not read-only)
        var commandTargetFromEntity = GetComponentDataFromEntity <CommandTargetComponent>(false);

        JobHandle playerScoresDep;
        //We grab all the player scores because we don't know who will need to be assigned points
        var playerScoreEntities = m_PlayerScores.ToEntityArrayAsync(Allocator.TempJob, out playerScoresDep);
        //we will need to grab the PlayerScoreComponent from our player score entities to compare values
        var playerScoreComponent = GetComponentDataFromEntity <PlayerScoreComponent>();


        //We now any entities with a DestroyTag and an PlayerTag
        //We could just query for a DestroyTag, but we might want to run different processes
        //if different entities are destroyed, so we made this one specifically for Players
        //We query specifically for players because we need to clear the NCE when they are destroyed
        //In order to write over a variable that we pass through to a job we must include "WithNativeDisableParallelForRestricion"
        //It means "yes we know what we are doing, allow us to write over this variable"
        var playerDestructionJob = Entities
                                   .WithDisposeOnCompletion(playerScoreEntities)
                                   .WithReadOnly(playerScoreEntities)
                                   .WithNativeDisableParallelForRestriction(playerScoreComponent)
                                   .WithNativeDisableParallelForRestriction(commandTargetFromEntity)
                                   .WithAll <DestroyTag, PlayerTag>()
                                   .ForEach((Entity entity, int nativeThreadIndex, in PlayerEntityComponent playerEntity, in GhostOwnerComponent ghostOwnerComponent) =>
        {
            // Reset the CommandTargetComponent on the Network Connection Entity to the player
            //We are able to find the NCE the player belongs to through the PlayerEntity component
            var state          = commandTargetFromEntity[playerEntity.PlayerEntity];
            state.targetEntity = Entity.Null;
            commandTargetFromEntity[playerEntity.PlayerEntity] = state;

            //Now we cycle through PlayerScores till we find the right onw
            for (int j = 0; j < playerScoreEntities.Length; j++)
            {
                //Grab the PlayerScore
                var currentPlayScoreComponent = playerScoreComponent[playerScoreEntities[j]];
                //Check if the player to destroy has the same NetworkId as the current PlayerScore
                if (currentPlayScoreComponent.networkId == ghostOwnerComponent.NetworkId)
                {
                    //We create a new component with updated values
                    var newPlayerScore = new PlayerScoreComponent {
                        networkId    = currentPlayScoreComponent.networkId,
                        playerName   = currentPlayScoreComponent.playerName,
                        currentScore = 0,
                        highScore    = currentPlayScoreComponent.highScore
                    };
                    // SetComponent<PlayerScoreComponent>(playerScoreEntities[j], newPlayerScore);
                    //The reason why we don't go with:
                    //SetComponent<PlayerScoreComponent>(playerScoreEntities[j],  newPlayerScore);
                    //is because SetComponent<PlayerScoreComponent>() gets codegen'd into ComponentDataFromEntity<PlayerScoreComponent>()
                    //and you can't use 2 different ones or else you get an 'two containers may not be the same (aliasing)' error
                    playerScoreComponent[playerScoreEntities[j]] = newPlayerScore;
                }
            }
            //Then destroy the entity
            commandBuffer.DestroyEntity(nativeThreadIndex, entity);
        }).ScheduleParallel(JobHandle.CombineDependencies(Dependency, playerScoresDep));