Nesta palestra, examinaremos 'Reunindo-se'.
Reunir tem que ser um dos meus A. favoritos EU. técnicas.
Envolve regras simples que geram comportamentos complexos que são fascinantes. O flocagem pode ser usado para gerar procedimentalmente o
movimento de grupos de indivíduos que gostam de ficar juntos, enquanto caminham em direção a
um objetivo comum.
O vôo dos pássaros vem à mente, mas essa técnica pode ser usada praticamente em qualquer lugar em que
você tenha um grupo que precise de comportamentos móveis complexos que você não deseja programar manualmente.
Neste workshop, criaremos peixes reunidos (ou escolarizados). Para acompanhar, faça o download do pacote 'AIfish'
Unity que acompanha esta palestra.
Abra um novo projeto do Unity para 3D e leve esse pacote.
Ao adicioná-lo ao recurso, você encontrará um peixe verde, um peixe rosa e uma cena chamada Natação. Se você abrir a cena da Natação, obterá
o peixe verde sozinho
com a câmera configurada para ele e se pressionar Play,
verá que esse peixe verde tem uma animação de natação anexada.
Agora, para criar o agrupamento, você precisa de mais de 1 peixe neste
caso, porque o agrupamento é uma atividade de grupo.
Então, vamos criar um Flocking Manager e,
na Hierarquia, clique com o botão direito do mouse lá e adicione um vazio e chame-o de FlockManager.
Isso não é diferente dos outros Gerentes que tivemos anteriormente para outros agentes, onde
queríamos criar várias versões deles para que possamos enviar mensagens e acompanhá-las.
Nesse caso, os peixes precisam conhecer um ao outro, para que o FlockManager crie um monte
de peixes e seja capaz de dizer a todos os indivíduos sobre os outros peixes no rebanho (ou escola, eu acho, mas eu estou
chamando de rebanho).
Certo, temos o nosso FlockManager, que é um 'vazio'. Crie um script C # e chame-o de FlockManager
e, em seguida, esse script será anexado ao nosso FlockManager.
Agora vamos abrir esse script e adicionar esse código. O código é bastante simples.
Ele cria uma variedade de peixes, instancia todos esses objetos de peixes e os coloca em um
local aleatório em torno do local do seu FlockManager.
Direita.
Então, antes de tudo, você precisará de uma variável exposta public fishPrefab e passamos aqui na nossa pré-fabricada de peixes (que pode ser
seu peixe verde ou rosa ou qualquer outra coisa). Você também pode fazer isso com cubos, não fará
nenhuma diferença e,
em seguida, um número público que definimos como 20 (mas isso permitirá que você altere o número de
peixes que você tem em um rebanho em particular, através de Inspetor).
Em seguida, criaremos nossa matriz de allFish e, à medida
que os instanciamos, eles entrarão nesse allFish e, em seguida, teremos um
Vector3 chamado swimLimits.
Esse é o intervalo de locais em que os peixes podem ser gerados.
Portanto, isso é como uma caixa que está ao redor do seu gerente de rebanho e é 5x5x5, o que a
torna 10x10x10, porque esse é um valor de
raio e, em seguida, usaremos os swimLimits para gerar a localização de nossos peixes dentro dessa caixa.
Então, tudo isso está acontecendo no Start.
Antes de tudo, criamos todos os peixes e aumentamos o tamanho da matriz para mantê-los.
Depois, há o loop 'for', que gira em torno desse número de vezes e
cada vez cria uma posição para colocar o peixe, e essa posição é baseada na posição do gerente do rebanho, mais um
valor Vector3 aleatório ao redor desses swimLimits (então entre 'menos swimLimits' e 'swimLimits positivo'),
que fornecerão o intervalo de posições.
Agora, se você deseja que ele seja uma caixa de posições maior, basta aumentar esses valores
aqui ou diminuir os valores, se quiser um grupo unido.
Então, uma vez que temos essa posição que calculamos, colocamos o peixe (instanciamos do
nosso pré-fabricado) na posição que acabamos de calcular, usando uma rotação neutra.
Você também pode definir isso para a
rotação pré-fabricada de peixes, se você os apontar em uma direção específica,
isso realmente não importa e isso preencherá essa matriz.
Portanto, se você salvar isso, volte para o Unity, selecione seu FlockManager e deseja definir a pré-fabricada de peixe.
O peixe pré-fabricado não é esse peixe verde que está em cena.
Está bem.
Então esse foi o usado para fazer a pré-fabricação inicial.
Na verdade, basta excluí-lo, para que você não fique confuso com ele e, em seguida, agarre sua pré-fabricada
de peixe (que está em seus ativos) e arraste e solte-a no FlockManager.
Vamos criar 20 peixes e ele preencherá essa matriz aqui.
Então pressione Play e seus 20 peixes (e se eu
diminuir o zoom, você os verá) dentro dos limites de natação que criamos.
Agora, se você quiser mais peixes do que isso, digamos que você queira 50 peixes ... 50 aqui e pressione Play e você receberá 50 peixes.
Você pode vê-los, todos eles apareceram na Hierarquia e no Inspetor, sob a matriz allFish, para
que
cada peixe possa encontrar todos os outros peixes que estão em seu rebanho.
Ok, é hora de colocar o peixe em movimento. Para começar, vamos definir alguns valores de velocidade para
o peixe e faremos isso no FlockManager. Portanto, tornaremos o FlockManager um local onde podemos definir
todas as variáveis diferentes para os peixes específicos que pertencem a esse rebanho e, em seguida,
você pode ter vários rebanhos para diferentes tipos de peixes em sua cena.
Então, estive com o script FlockManager novamente. O que você vai fazer é adicionar alguns valores públicos
como eu tenho aqui.
Primeiro, no Inspetor, acabei de adicionar uma pequena linha de 'Cabeçalho', que a separa e facilita a localização
quando você está tentando defini-las.
Então eu tenho um 'Range' aqui, entre 0. 0f e 5. 0f que fornecerá
um controle deslizante no Inspetor e, em seguida, minSpeed público e maxSpeed público, com os mesmos valores para o intervalo.
Depois de adicionar essas 5 linhas, salve isso e volte para o Unity, clique no Flock Manager e
você encontrará no Inspector que agora temos essas configurações. Temos 'Fish Settings', Min e Max Speed (que você pode
alterar com os controles deslizantes que quiser e poderá fazer isso em tempo real também e
passar esses valores de velocidade para o peixe) . Para os peixes, agora criaremos um
novo arquivo C # e o chamaremos de 'Flock'.
Este é o código que segue para a pré-fabricação de peixes, então arraste e solte no seu peixe verde e enquanto estivermos
aqui, nós o arrastaremos e soltaremos no peixe rosa também.
Basta selecionar o peixe verde em Ativos e verificar no Inspetor para garantir que o script esteja realmente
anexado a ele.
Agora abra-o e a primeira coisa que precisaremos é um link para o
nosso gerente, por isso criaremos um 'FlockManager público myManager' e, em seguida, precisaremos de um flutuador para a velocidade.
Agora, no Start, vamos definir a velocidade como igual a Random. Intervalo entre a configuração de velocidade mínima dos gerentes e a configuração de
velocidade máxima dos gerentes. Na atualização, colocaremos
uma instrução Translate para impulsionar o peixe para frente ao longo do eixo dianteiro ou do eixo Z.
Portanto, observe que o valor de 'speed' está indo para o eixo Z.
Se o seu peixe estiver em uma direção diferente ...
então, se eu voltar para o meu peixe e pegar um peixe, o eixo azul aqui está voltado para a frente e é esse
que ele o empurrará.
Se o seu peixe tiver um eixo diferente, será necessário ajustar seu código para empurrá-lo ao
longo desse eixo.
Ok, vamos excluir o peixe e voltar ao código e salvá-lo. Em seu script FlockManager,
se o abrirmos, depois de criar um peixe dentro desse loop for, você deseja definir é FlockManager
(ou myManager) para este FlockManager em particular.
Portanto, adicione esse código e agora os dois arquivos (o Flock e o FlockManager) serão vinculados.
De volta ao Editor, pressione Play e você verá os resultados do código.
Então você tem o seu peixe que está avançando agora.
Eles têm velocidades aleatórias neles.
Claro, eles vão sair de cena muito rapidamente.
Você pode ver que eles estão se movendo em velocidades diferentes (se você puder se aproximar). Sim.
Então, todos eles têm velocidades diferentes,
mas todos estão se movendo ao longo do eixo Z. Ok, agora é hora de adicionar nossas 'regras de agrupamento'.
Mencionei as regras de agrupamento no início desta
seção, mas vamos examiná-las novamente, em detalhes.
São eles: Mover para a posição média do grupo; Alinhe com o cabeçalho médio do grupo e
evite aglomerar outros membros do grupo.
Avançar para a posição média do grupo envolve assumir todas as posições individuais dos
membros, juntando-as e dividindo pelo número do grupo.
Podemos então descobrir onde está um indivíduo, em relação à localização média e fazer com que ele
se volte para ele. Para alinhar com o
cabeçalho médio do grupo, adicionamos todos os cabeçalhos dos indivíduos e dividimos pelo tamanho do grupo.
Isso fornece um vetor médio para os indivíduos tentarem alinhar seus movimentos. Para evitar vizinhos, um indivíduo deve estar ciente
de onde os vizinhos
estão e depois se afastar deles.
Em seguida, para calcular um novo título, um indivíduo adicionará o vetor para avançar em direção ao centro
de um grupo, o vetor para alinhar com o título do grupo e o vetor para se afastar de um vizinho.
Antes de começarmos a editar o código do Flock, adicionaremos mais alguns valores ao FlockManager (aqueles
que você pode alterar em tempo de execução, para poder ver comportamentos diferentes no
peixe) e essas configurações para os comportamentos serão disponível para todos os peixes desse rebanho
em particular.
Então, eu estou adicionando aqui outro Range para algo chamado neighbourDistance e outro Range para
rotationSpeed.
Assim que os peixes começarem a encontrar locais para os quais precisam se mover, eles terão que se virar em
algum momento e usaremos um slerp para isso e isso precisa de uma velocidade de rotação, então
eu adicionei que lá.
Agora, a outra coisa com essa vizinhançaDistância é que você pode ter um bando de alguma coisa e tudo nesse bando
pode ser considerado seu vizinho ou
você pode apenas considerar os poucos mais próximos (a um metro de você) como seu vizinho real, então
portanto, você pode modificar isso e obter comportamentos diferentes de todo o grupo quando eles
consideram apenas os que estão imediatamente ao seu redor como vizinhos e não como todos.
Agora, as mudanças no rebanho. Vá para o seu rebanho. código cs.
Vamos criar um novo método chamado 'ApplyRules' e esse método está sendo chamado aqui em baixo, para
que não haja outras alterações na parte superior, apenas dentro da Atualização
e, em seguida, adicionamos o ApplyRules.
Agora, este ApplyRules está fazendo essas três regras sobre as quais acabamos de falar, com os diferentes cálculos de vetores.
Antes de tudo, é criar um suporte para se apossar de todos os peixes do rebanho atual.
Então, esses são os peixes que queremos tentar e encontrar a posição média, a posição média etc. e eles são os peixes que serão
considerados seus vizinhos (ou pelo menos são o conjunto inteiro e os vizinhos farão
parte desse conjunto, como você verá em um minuto).
Agora estamos calculando o centro médio dos grupos, então vamos armazenar isso no 'vcentre'. Então, estamos calculando
o vetor médio de prevenção também.
Portanto, não é apenas um vizinho que queremos evitar,
é TODOS e
isso também é uma média.
Então você tem que calcular todos os vetores de evasão e depois calculá-los.
Então, inicialmente, eles são definidos como 0.
Então temos esse flutuador
chamado 'gSpeed' e essa é uma velocidade global do grupo (uma velocidade média na qual o grupo
está se movendo) e usaremos isso também em nossos cálculos.
Então nós temos um float 'nDistance', que é a nossa distância vizinha.
Então, teremos que perguntar a cada peixe a que distância eles estão e
depois trabalhar se considerarmos que eles estão
próximos o suficiente para estar em nosso grupo e, por isso, temos esse contador 'groupSize' aqui, que contará quantas peixes no rebanho estão
no nosso grupo, então o grupo é como esta pequena seção do rebanho que está dentro desse valor de
neighbourDistance.
Agora, com esses valores inicializados em 0, essencialmente, vamos percorrer todos os
peixes do rebanho.
Então, usamos um loop foreach.
Então, perguntaremos se o peixe atual (que será o objeto do jogo
aqui: vá), contanto que
não seja igual ao peixe que está executando esse código no momento, faremos o processo porque você não precisa
encontrar a média de si mesmo, não precisa calcular a
distância
para si mesmo; portanto, isso garante que não calculemos os dados dos peixes para si.
Depois, calculamos a distância do vizinho; lembre-se de que estamos contornando esse loop for, escolhendo
cada peixe e calculando a distância com um Vector3. Distância entre o objeto de jogo em
nossa posição de matrizes e nossa posição no mundo e, em seguida, perguntamos se essa distância
é 'menor ou igual a' neighbourDistance, o que torna esse peixe de interesse (aquele
que vamos (considere parte de nosso grupo unido), então adicionaremos a posição desse peixe em particular ao 'vcentre'.
vcentre será a nossa posição média do nosso grupo, portanto,
temos que dar voltas e adicionar todas as posições juntas e depois
a dividimos pelo tamanho do grupo.
Portanto, ao mesmo tempo em que o adicionamos, também aumentamos o tamanho do grupo em 1.
Então, depois que esse loop passar, podemos calcular a média.
Em seguida, temos uma instrução if para testar nosso neighbourDistance sendo menor que um valor muito menor, que eu
codifiquei aqui como 1. 0 e
poderíamos, de fato, colocar isso no FlockManager como outro valor de distância, mas este
é o quão perto estamos de outro peixe antes de pensarmos em evitá-lo.
Agora, se, neste caso, a distância for menor que 1. 0f, o vetor médio de evitação será
adicionado e, portanto, terá seu próprio valor + o vetor do peixe.
Portanto, o vetor que está longe de algo (e analisamos isso em uma simulação de multidão
que queríamos nos afastar) era a nossa posição atual menos a posição da qual
queremos nos afastar e isso aumenta quando passamos por aqui também.
Agora, a velocidade global está agregando todas as velocidades de um determinado peixe do rebanho.
Então, vamos em frente e agarramos o código do Flock que está anexado ao peixe
que estamos vendo no momento e, então, agarramos sua velocidade e o adicionamos a esse valor de gSpeed.
Agora, quando o código termina esse loop foreach, passamos por todos
os peixes do rebanho e o examinamos. Se é considerado um vizinho próximo, então estamos descobrindo sua posição e
também seu vetor de fuga e somando tudo isso.
Ah, e claro, a velocidade. Agora, abaixo do loop
foreach, temos uma declaração if. A instrução if está perguntando se o tamanho do grupo é> 0. Se o peixe estiver se movendo
e não houver ninguém ao seu redor e o tamanho do grupo se tornar 0,
não aplicará essas regras. Só vai continuar se movendo em linha reta.
Portanto, se este peixe é influenciado por outro peixe (ou outro grupo de peixes), então encontramos a média para o
centro.
Portanto, esse é o vetor 'vcentre' que calculamos quando os
adicionamos, agora dividimos pelo tamanho do grupo. A velocidade do peixe é definida para a velocidade global,
dividida pelo tamanho do grupo.
Com essas informações, podemos determinar a direção em que o peixe precisa viajar (ou a direção
em que o peixe deseja viajar).
Portanto, sua 'direção' é igual à 'matriz vcentre' + 'matriz vavoid' - nossa posição atual.
Agora, se isso significa que a direção é 0, já estamos voltados
para a direção certa.
Se não for igual a zero, precisamos
rotacionar e, portanto, fazemos uma transformação. rodamos e usamos nosso Slerp que usamos anteriormente para outros NPCs e
fazemos uma pequena rotação de acordo com nossa velocidade de rotação e o que isso fará é
girar lentamente o peixe na direção que ele precisa. Ele não vai encaixar na direção
perfeita e é
esse slerp (e deslizando um pouquinho por um pouquinho) e constantemente atualizando sua
posição e verificando onde você está com relação a todos os outros peixes, que causa esse aglomerado
ocorrer, como você está prestes a ver. O tempo neste vídeo está prestes a acabar, então rapidamente
pressionaremos Reproduzir (verifique se no FlockManager você fornece uma Distância vizinha e uma Velocidade de rotação, caso
contrário você não terá nenhuma rotação
e depois você começará a ver o aglomerado ocorrendo.
Investigaremos isso mais no próximo vídeo.