Scripting and Modding ‐ Simplified Version - Outerra/anteworld GitHub Wiki
* this tutorial is meant to be followed after you import the vehicle via asset importer.
Step 1 - Preconfiguration
As of now, the vehicle can be selected in the assets window. But right now the game doesn't know it is a vehicle.
- To fix that, go to the file the Asset Importer created and open the
.objdef
file (via Notepad for example). - Now set the
physics
tovehicle
. Then set thescript
tomy_script.js
(or whatever you want to call your script. - Finally, create a JavaScript file in the folder and call it
my_script.js
- it MUST have the same name as what you set in the.objdef
file asscript
. Or, you can just copy a script from here:Outerra World Sandbox\prg\game\mods\example_models_js\packages\tutorial_car_js
- considering we will use its content.
This is all we needed for the first step. In order to check if you did it correctly, go to the game, press F3 and search for your vehicle.
Step 2 - Configuration
Secondly, paste the template file's content to your script. (If you coped the template file in the first place, you don't need to). Now edit it.
Now, you get to configure some properties of your vehicle. For the basics, you don't have to care about the second part of the code - just the configurable parts.
1. Basic Settings
const ENGINE_FORCE = 25000.0; // Newtons
const BRAKE_FORCE = 5000.0; // Newtons
const MAX_KMH = 200; // Km/h; maximal speed of vehicle
const MASS = 1120; // kg
This is the first part of the code.
MAX_KMH
is the maximal speed of the vehicle.MASS
is its weightENGINE_FORCE
andBRAKE_FORCE
essentially determine the acceleration or the braking speed of the vehicle.
2. Camera Position
let camera_fps_position = {
x: -0.4,
y: 0.16,
z: 1.3
}
Edit x, y and z (x, y, z axis) so that it will correspond with the driver's view (first person view). - This is usually done by trial and error - you edit the value and see if it is closer to your desired view, or further away, and the change it. You can also figure it out by going to your 3D software and see how far away the view is from the center of the vehicle. That might however require thinking.
Example of a correct FPS position:
3. Wheel Configuration
In the first part of the code, you must list all the wheels your vehicle has. Note that it must refer to the bones which are attached to the corresponding wheels, it cannot be the wheel object itself. If your model doesn't have bones, you unfortunately have to fix that and reimport it.
Start by defining a list of wheel IDs. Each wheel gets a variable initialized with -1. The names are arbitrary but should match the number of wheels on your vehicle.
Example for an 8-wheel bus:
let wheels = {
FLwheel: -1,
FRwheel: -1,
MLwheel: -1,
MRwheel: -1,
XRwheel: -1,
XLwheel: -1,
RLwheel: -1,
RRwheel: -1,
};
This concrete example is from a large bus with 8 wheels. If you are creating for example a car, with only 4 wheels, remove the last 4, so it would look like this:
let wheels = {
FLwheel: -1,
FRwheel: -1,
MLwheel: -1,
MRwheel: -1,
};
Next, connect each wheel ID to its corresponding bone name in your model using add_wheel()
:
function set_wheels(){
wheels.FLwheel = this.add_wheel('wheel_1_L', wheel_params);
wheels.FRwheel = this.add_wheel('wheel_1_R', wheel_params);
wheels.MLwheel = this.add_wheel('wheel_2_L', wheel_params);
wheels.MRwheel = this.add_wheel('wheel_2_R', wheel_params);
wheels.XLwheel = this.add_wheel('wheel_3_L', wheel_params);
wheels.RRwheel = this.add_wheel('wheel_4_R', wheel_params);
wheels.XRwheel = this.add_wheel('wheel_3_R', wheel_params);
wheels.RLwheel = this.add_wheel('wheel_4_L', wheel_params);
The part 'wheel_1_L'
is the bone name, wheel FLwheel
holds the id. DO NOT modify the wheels.
part, nor the = this.addwheel('
part, just the concrete names of the bones/names. Again, you should have as many add_wheels
as you have got wheels.
Now, for the last part, you get to modify the wheel parameters:
let wheel_params = {
radius: 0.6,
width: 0.2,
suspension_max: 0.1,
suspension_min: -0.04,
suspension_stiffness: 50.0,
damping_compression: 0.4,
damping_relaxation: 0.12,
grip: 1,
};
The most relevant part for configuration is radius
. It is in meters and it represents the size of your wheels. If you set it too high, your vehicle will float. If you set it too low, your vehicle will be stuck and sunk in the ground. You can set it again by trial and error, or by measuring the vehicle's wheel radius.
In the case, that you have a vehicle which has more wheels of different sizes, copy the code and paste it below it. Just change the name to something else, like wheel_params_2
. Then go back to set_wheels
and set parameters to wheel_params_2
for each wheel of that given size.
Other settings
Finally, you have to select which wheels are going to be powered and which are going to be steerable. Just add those which you want to be powered to powered_wheels
and those which you want to be steerable to steer_wheels
(Again, modify only the name, like FLwheel
, and nothing else. If you want more, copy the line and put it below.) Usually, the front wheels are both steerable and powered. You always have to set at least one for each, ideally two. Else, your vehicle won't move or steer.
function powered_wheels(force){
this.wheel_force(wheels.FLwheel, force);
this.wheel_force(wheels.FRwheel, force);
}
function steer_wheels(steering){
this.steer(wheels.FLwheel, steering);
this.steer(wheels.FRwheel, steering);
}
By now, you should be able to:
- Enter the vehicle
- Start the vehicle by pressing E
- Reverse the vehicle by pressing R
- Drive the vehicle, it should accelerate naturally
Step 3 - Animations and other elements
Step 4 - Lights
For lights, you first must lay out all light types you will have. For example, if you have white headlights and red taillights, create separate property objects for each.
light_props = {
size: 0.1,
angle: 160,
edge: 0.8,
color: {
x: 0,
y: 0,
z: 0
},
intensity: 0,
range: 150,
fadeout: 0.05
};
size
sets the diameter.angle
set the angle of the light (how wide it is), for example:
edge
decides how soft/hard your light is.color
decides its color, thex, y, z
values are essentiallyrgb
codes, wherex
isr
and so on. So, if you want a red light, set thex
value to1
.intensity
decides intensity, the higher the value, the more intense the light.range
decides its range, how far it will getfadeout
decides the time it takes to fade out after turning off.
Then after you create one type of lights, copy the code and add another below it, change the name and change the properties.
Adding the lights
Then, when you are done setting the light properties, you have to place them. You can position and aim the lights using the add_spot_light()
function:
this.add_spot_light(
{ x: -0.55, y: 2.2, z: 0.68 }, // Position
{ y: 1.0 }, // Direction
light_props // Properties
);
- The first object sets the light’s position.
- The second defines the direction it points.
- The third references the property object you created earlier.
You can also add an additional fourth argument, which decides which bone should the light be attached to. Example of use:
this.add_spot_light(
{ x: -0.05, y: -0.06, z: 0.0 },
{ y: 1.0 },
light_props,
"tail_light_l0"
); // Left tail light
where tail_light_10
is the name of the bone.
Texture Loading
In order to load textures for the model, all you have to import it via the asset importer. Sometimes, it errs and cannot properly distinguish all the file names. [INSERT NAMING CONVENTIONS] In that case, you will have to add them manually. Just open the material editor in game:
If you do not have a texture pre-made, you can just toggle some of the values - set the color, roughness and etc. But if your material had the values set, the game would set them also.
In the material editor, you first select the material you want to edit. (The list of materials are the same as they were in the model you created, whatever you named them). You have to edit some of the values in order to make it look as you wish to.
There is the First Block and the Second Block (delimited by the three checkboxes).
- The Second Block allows you to link the model with texture maps in your folders.
- The First Block is used when you don’t have pre-made textures, and you just want to put some simple values, for example make the whole material rough.
- Note: The available options in the First Block will change automatically when you add a texture map in the Second Block.
For example, this is how the options change once you put a roughness map in there: More precisely:
Turns into:
Now you can no longer set one uniform roughness for the whole material. But you can toggle it a bit, make the rough parts less parts, or the smooth parts more rough. Or both. Or if you included an emissive map, you will be able to do this with emission instead of roughness.
- Some maps do not have this options and some have different ones
- This is done because the properties may look different in-game and in your 3D modeling software.