JOHAN TORP DICE CODERS DAY 311 2010 JOHAN

  • Slides: 27
Download presentation
JOHAN TORP DICE CODERS DAY 3/11 2010 <JOHAN. TORP@DICE. SE>

JOHAN TORP DICE CODERS DAY 3/11 2010 <JOHAN. TORP@DICE. SE>

› AI decision making - Pathfinding - Animation › Look at actual code &

› AI decision making - Pathfinding - Animation › Look at actual code & patterns › Questions

AI DECISION MAKING OO PATHFINDING ANIMATION NAVPOWER OO OO

AI DECISION MAKING OO PATHFINDING ANIMATION NAVPOWER OO OO

› › › Find path Load / unload nav mesh section Add / remove

› › › Find path Load / unload nav mesh section Add / remove obstacles Path invalidation detection Can go-tests “Raycasts”, circle tests, triangle tests

› Pathfinder - find path, path invalidation, circle tests, raycasts › Random position generator

› Pathfinder - find path, path invalidation, circle tests, raycasts › Random position generator - can go-tests › Manager - load nav mesh, obstacles, destruction, updates Left some raycasts synchronous

› › › › interface Pathfinder { public: virtual Path. Handle* find. Path(const Pathfinding.

› › › › interface Pathfinder { public: virtual Path. Handle* find. Path(const Pathfinding. Position& start, const Pathfinding. Position& end, Optional<float> corridor. Radius, Path. Handle: : State. Listener* listener) = 0; › › › /// More efficient version of find. Path when start is the end of a previous path /// @pre last. Path->get. State() == Path. Handle: : Valid. Path virtual Path. Handle* find. Path. From. Destination(Path. Handle* last. Path, const Pathfinding. Position& end, Optional<float> corridor. Radius, Path. Handle: : State. Listener* listener) = 0; › virtual void release. Path(Path. Handle* path) = 0; › › virtual bool can. Go. Straight(Vec 3 Ref start, Vec 3 Ref end, Vec 3* collision = nullptr) const = 0; };

› › typedef fixed_vector<Vec 3, 16> Waypoint. Vector; typedef fixed_vector<float, 16> Waypoint. Radius. Vector;

› › typedef fixed_vector<Vec 3, 16> Waypoint. Vector; typedef fixed_vector<float, 16> Waypoint. Radius. Vector; › › › struct Path. Handle { enum State {Computing. Path, Valid. Path, No. Path. Available, Repathing. Required}; › › › interface State. Listener { virtual void on. State. Changed(Path. Handle* handle) = 0; }; › Path. Handle() : waypoints(pathfinding. Arena()), radii(pathfinding. Arena()) {} › › Waypoint. Vector waypoints; Waypoint. Radius. Vector radii; › › State state; };

› › typedef eastl: : fixed_vector<Vec 3, 16> Waypoint. Vector; typedef eastl: : fixed_vector<float,

› › typedef eastl: : fixed_vector<Vec 3, 16> Waypoint. Vector; typedef eastl: : fixed_vector<float, 16> Waypoint. Radius. Vector; › › › struct Path. Handle { enum State {Computing. Path, Valid. Path, No. Path. Available, Repathing. Required}; › › › interface State. Listener { virtual void on. State. Changed(Path. Handle* handle) = 0; }; › Path. Handle() : waypoints(pathfinding. Arena()), radii(pathfinding. Arena()) {} › › Waypoint. Vector waypoints; Waypoint. Radius. Vector radii; › › State state; };

› › › class Nav. Power. Pathfinder : public Pathfinder { public: virtual Path.

› › › class Nav. Power. Pathfinder : public Pathfinder { public: virtual Path. Handle* find. Path(. . . ) override; virtual Path. Handle* find. Path. From. Destination(. . . ) override; virtual void release. Path(. . . ) override; virtual bool can. Go. Straight(. . . ) const override; void update. Paths(); void notify. Path. Listeners(); › › › private: bfx: : Polyline. Path. RCPtr m_paths[Max. Paths]; Path. Handle m_path. Handles[Max. Paths]; Path. Handle: : State. Listener* m_path. Handle. Listeners[Max. Paths]; u 64 m_used. Paths; › › typedef eastl: : fixed_vector<Path. Handle*, Max. Paths, false> Path. Handle. Vector; Path. Handle. Vector m_updated. Paths, m_updated. Valid. Paths; };

› typedef eastl: : vector<Corridor. Node> Corridor; › › › Scratch. Pad. Arena scratch;

› typedef eastl: : vector<Corridor. Node> Corridor; › › › Scratch. Pad. Arena scratch; Corridor corridor(scratch); corridor. resize(nav. Power. Path. size()); // Will allocate memory using the scratch pad 1. 2. 3. 4. Copy all new Nav. Power paths -> temporary representation Drop unnecessary points Corridor adjust paths who requested it Copy temporaries -> Path. Handles

› › const Corridor. Handle. Vector: : iterator all. Begin = all. begin(), all.

› › const Corridor. Handle. Vector: : iterator all. Begin = all. begin(), all. End = all. end(); const Corridor. Handle. Ptr. Vector: : iterator adjust. Begin = adjust. begin(), adjust. End = adjust. end(); › › for (Corridor. Handle. Vector: : iterator it=all. Begin; it!=all. End; ++it) drop. Unnecessary. Points(it->corridor, scratch. Pad); › › for (Corridor. Handle. Ptr. Vector: : iterator it=adjust. Begin; it!=adjust. End; ++it) shrink. End. Points((**it). corridor, m_id); › › for (Corridor. Handle. Ptr. Vector: : iterator it=adjust. Begin; it!=adjust. End; ++it) calculate. Corner. Displacements((**it). corridor); › › for (Corridor. Handle. Ptr. Vector: : iterator it=adjust. Begin; it!=adjust. End; ++it) displace. Corners((**it). corridor, m_id); › › for (Corridor. Handle. Ptr. Vector: : iterator it=adjust. Begin; it!=adjust. End; ++it) shrink. Sections((**it). corridor, m_id); › › } for (Corridor. Handle. Vector: : iterator it=all. Begin; it!=all. End; ++it) copy. Corridor. To. Handle(it->corridor, *it->handle);

› › void Nav. Power. Manager: : update(float frame. Time) { m_streaming. Manager. update();

› › void Nav. Power. Manager: : update(float frame. Time) { m_streaming. Manager. update(); m_destruction. Manager. update(); › m_obstacle. Manager. update(); › bfx: : System. Simulate( frame. Time ); › › for (Pathfinder. Vector: : const_iterator it=m_pathfinders. begin(), . . . ) (**it). update. Paths(); › for (Pathfinder. Vector: : const_iterator it=m_pathfinders. begin(), . . . ) (**it). notify. Path. Listeners(); › › for (Position. Generator. Vector: : const_iterator it=m_position. Generators. begin(), end =. . . ) (**it). update(); }

› › Keep pathfinding code/data cache hot Avoid call sites cache running cold Easier

› › Keep pathfinding code/data cache hot Avoid call sites cache running cold Easier to jobify / SPUify Easy to timeslice

› Manager › Random position generator › Pathfinder Collect destruction messages, process in batch

› Manager › Random position generator › Pathfinder Collect destruction messages, process in batch Runs ~1/sec. Allows synchronous decisions Decision making assumes success

SCRIPTING SERVER CLIENT AI DECISION MAKING PATH FOLLOWING PATHFINDING NAVPOWER DRIVING VEHICLE INPUT LOCOMOTION

SCRIPTING SERVER CLIENT AI DECISION MAKING PATH FOLLOWING PATHFINDING NAVPOWER DRIVING VEHICLE INPUT LOCOMOTION Waypoints Waypoint Data Corridor Radii ANIMATION

Each server tick 1. Each AI decision making 2. Pathfinding manager update All pathfinding

Each server tick 1. Each AI decision making 2. Pathfinding manager update All pathfinding requests All corridor adjustments All Path. Handle notifications -> path following -> server locomotion 3. Network pulse. Server locomotion -> client locomotion 4. . rest of tick

› › › Callbacks. Delay? Fire in batch? Handle+poll instead of callbacks. Poll in

› › › Callbacks. Delay? Fire in batch? Handle+poll instead of callbacks. Poll in batch. Record messages, process all once a frame Check success / failure next frame Pre-calculate what you’re likely to need Con: Callstack won’t tell you everything. . but can we afford deep callstacks?

› › › void Bot: : change. Vehicle(const Server. Entry. Component* entry) {. .

› › › void Bot: : change. Vehicle(const Server. Entry. Component* entry) {. . . m_path. Follower = entry->owner()-> get. First. Component. Of. Type<Server. Path. Following. Component>()->get. Path. Follower(); }

new / push_back() / insert() / resize() Stop and think! › › › Where

new / push_back() / insert() / resize() Stop and think! › › › Where is the memory allocated? Pre-allocated containers? Scratch pad? Can I resize()/reserve() immediately? Can I use Optional<T> instead of Scoped. Ptr<T>? Can I use vectors instead of list / set / map?

› Let’s not abandon OO nor rewrite the world › Start small, batch a

› Let’s not abandon OO nor rewrite the world › Start small, batch a bit, resolve inputs, avoid deep dives, grow from there › Much easer to rewrite a system in a DO fashion afterwards

AI decision making – pathfinding – animation Code: Handles, arena, scratch pad, fixed_vector, batch

AI decision making – pathfinding – animation Code: Handles, arena, scratch pad, fixed_vector, batch processing Latency analysis, async patterns Think about depth/width of calls, try stay within your system, resolve early, new/push_back() = think

› johan. torp@dice. se

› johan. torp@dice. se