官术网_书友最值得收藏!

Creating a group of followers

In this example, we're going to build another AI type called a follower agent. This time, a group of followers will stay together and move toward their leader. The leader, on the other hand, is still the same seeking agent that will randomly move around the sandbox, completely oblivious to the group of followers behind it.

Group-based movement using separation, cohesion, and alignment

To create followers, we'll use multiple steering forces to combine, separate, and align our agents to the leader agent they are following.

Create the Lua file as follows:

src/my_sandbox/script/FollowerAgent.lua

FollowerAgent.lua:

require "AgentUtilities";

local leader;

function Agent_Initialize(agent)
    AgentUtilities_CreateAgentRepresentation(
        agent, agent:GetHeight(), agent:GetRadius());

    -- Randomly assign a position to the agent.
    agent:SetPosition(Vector.new(
        math.random(-50, 50), 0, math.random(-50, 50)));

    -- Assign the first valid agent as the leader to follow.
    local agents = Sandbox.GetAgents(agent:GetSandbox());
    for index = 1, #agents do
        if (agents[index] ~= agent) then
            leader = agents[index];
            break;
        end
    end
end

function Agent_Update(agent, deltaTimeInMillis)
    local deltaTimeInSeconds = deltaTimeInMillis / 1000;
    local sandboxAgents = Sandbox.GetAgents(agent:GetSandbox());

    -- Calculate a combining force so long as the leader stays
    -- within a 100 meter range from the agent, and has less than
    -- 180 degree difference in forward direction.
    local forceToCombine =
        Agent.ForceToCombine(agent, 100, 180, { leader } );

    -- Force to stay away from other agents that are closer than
    -- 2 meters and have a maximum forward degree difference of
    -- less than 180 degrees.
    local forceToSeparate =
        Agent.ForceToSeparate(agent, 2, 180, sandboxAgents );

    -- Force to stay away from getting too close to the leader if
    -- within 5 meters of the leader and having a maximum forward
    -- degree difference of less than 45 degrees.
    local forceToAlign =
        Agent.ForceToSeparate(agent, 5, 45, { leader } );

    -- Summation of all separation and cohesion forces.
    local totalForces =
        forceToCombine + forceToSeparate * 1.15 + forceToAlign;
    
    -- Apply all steering forces.
    AgentUtilities_ApplyPhysicsSteeringForce(
        agent, totalForces, deltaTimeInSeconds);
    AgentUtilities_ClampHorizontalSpeed(agent);
    
    local targetRadius = agent:GetTargetRadius();
    local position = agent:GetPosition();
    local destination = leader:GetPosition();
    
    -- Draw debug information for target and target radius.
    Core.DrawCircle(
        position, 1, Vector.new(1, 1, 0));
    Core.DrawCircle(
        destination, targetRadius, Vector.new(1, 0, 0));
    Core.DrawLine(position, destination, Vector.new(0, 1, 0));
end

Our following agent is very similar to the pathing agent; it first finds a leader during the initialization and then uses cohesion and alignment steering forces to try and stay as close to the leader as possible while using a separation force at the same time to stay at least two meters away from all other agents, including the leader:

Sandbox.lua:

function Sandbox_Initialize(sandbox)

    ...
    
    -- Create a pursuing agent to follow the seeking agent.
    Sandbox.CreateAgent(sandbox, "PursuingAgent.lua");

    -- Create a group of followers that follow the seeking agent.
    for i=1, 5 do
        Sandbox.CreateAgent(sandbox, "FollowerAgent.lua");
    end

    ...

end

Creating five followers and drawing debug circles around them for their separation areas makes it very easy to see how each force applies to the agent's movements.

Creating a group leader and followers.

主站蜘蛛池模板: 黄大仙区| 雷波县| 白山市| 蒙山县| 溧水县| 鞍山市| 西城区| 璧山县| 新巴尔虎右旗| 大余县| 定陶县| 大兴区| 玛多县| 泰兴市| 绥宁县| 新宾| 海口市| 敖汉旗| 孟村| 侯马市| 垣曲县| 咸丰县| 临洮县| 武清区| 平安县| 康乐县| 东宁县| 乃东县| 宁德市| 东阿县| 星子县| 额济纳旗| 和静县| 伊金霍洛旗| 南昌市| 广元市| 策勒县| 贵德县| 凉山| 乐东| 黑水县|