-
Notifications
You must be signed in to change notification settings - Fork 2
Tutorial ‐ Step 3
The aim here is to enable simple interactions from the VR headset. In particular, we want to be able to block roads by selecting them with the interaction ray. We'll then look at other types of interaction, with the example of using a button on one of the controllers to change the brightness.
First, we will modify the "Traffic and Pollution.gaml" file to integrate the notion of blocked roads. In the road species, we will add a boolean blocked attribute (initial value: false), and change the color of blocked road from white to red.
//Species to represent the roads
species road {
//Capacity of the road considering its perimeter
float capacity <- 1 + shape.perimeter / 30;
//Number of people on the road
int nb_people <- 0 update: length(people at_distance 1);
//Speed coefficient computed using the number of people on the road and the capicity of the road
float speed_coeff <- 1.0 update: exp(-nb_people / capacity) min: 0.1;
int buffer <- 10;
bool blocked <- false;
aspect default {
draw (shape + 5) color:blocked ? #red: #white;
}
}
We will then modify the reflex update_road_speed of the global section to take into account the fact that speed on a blocked road will be close to 0.
//Reflex to update the speed of the roads according to the weights
reflex update_road_speed {
road_weights <- road as_map (each::(each.shape.perimeter / each.speed_coeff * (each.blocked ? 100000.0 : 1.0)));
road_network <- road_network with_weights road_weights;
}
We're going to add an action to block a specific road (based on its name) in the Unity Linker species. In order to make a direct link between roads and their names, we've defined a map called "roads" that allows you to obtain the right road directly from a road name. This action will be called directly from Unity. If the route is not null, if the route is already blocked, the action will unblock it, and block it otherwise.
map<string,road> roads <- road as_map (each.name :: each);
action block_road(string id) {
road b <- roads[id];
if (b != nil) {
ask b {
if (not blocked) {
blocked <- true;
} else {
blocked <- false;
}
}
}
}
The first step is to extend the ray interaction distance. Inspect "GodViewPlayer/XR Origin (XR Rig)/Camera Offset/Right Controller/Ray Interactor", then set the "Max Raycast Distance" (in "XR Ray Interactor/Raycast Configuration") to 500 and in "XR Interactor Line Visual" uncheck "Override Line Length".
The second step is to specify what will happen when the player points the ray at a route and selects it. Open the script Assets/Gama Provider/SimulationManager. In this script, 3 functions control the XR-interaction: HoverEnterInteraction, HoverExitInteraction and SelectInteraction.
HoverEnterInteraction specifies what happens when the player passes over an object that can be interacted with. In the example given by default in the code, the object changes color to blue.
HoverExitInteraction specifies what happens when the player is no longer in contact with an object that can be interacted with. In the example given by default in the code, the object changes color and reverts to gray if not selected, or red otherwise.
SelectInteraction specifies what happens when the player selects an object (by default using the controller's second trigger - the white button along the handle). In the default example, if it's an object with the "interactable" tag, Unity triggers a GAMA action ("update_hotspot") which takes the name of the selected object as an argument and change the color of the object to red. Note that to prevent the player from pressing several times on the object too quickly, a timer is used to prevent a second action before "timeWithoutInteraction" seconds (set to 1s by default). For our tutorial, we'll just modify the name of the action to be called: instead of "update_hotspot", we'll call the "block_road" action we've just defined in the unity Linker (GAMA model).