JOHAN TORP DICE CODERS DAY 311 2010 JOHAN
- Slides: 27
JOHAN TORP DICE CODERS DAY 3/11 2010 <JOHAN. TORP@DICE. SE>
› AI decision making - Pathfinding - Animation › Look at actual code & patterns › Questions
AI DECISION MAKING OO PATHFINDING ANIMATION NAVPOWER OO OO
› › › 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 - can go-tests › Manager - load nav mesh, obstacles, destruction, updates Left some raycasts synchronous
› › › › 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; › › › 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, 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. 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; 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. 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(); 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 to jobify / SPUify Easy to timeslice
› 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 Waypoints Waypoint Data Corridor Radii ANIMATION
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 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) {. . . 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 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 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 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
- Coders day
- Day 1 day 2 day 3 day 4
- Coders corner
- Coders guru
- Johan andersson dice
- Hans torp
- Torp y sage 1998
- Hanna torp
- Svend torp
- Day 1 day 2 day 817
- 311 k
- Coen311
- Csc 311
- In 311
- Accounting 311
- Uw cse 311
- Psyc 311 study guide
- Psyc 311 textbook notes
- Psyc 311
- Comp 311 textbook notes
- Ise 311
- 311 rounded to the nearest ten
- Eecs 311
- Coen 311 concordia
- Chinese remainder theorem example
- Exchange server demo
- Tutela provisória art 294 a 311
- Sta 311 pdf