SDK and docs are unfinished.
Go to discord mod development channel for live support. ( https://discord.gg/UNwnxRzRen )
(Mod SDK will update a few days before major game update. In that short period, mod builds will only work in beta)
Some features are missing.
There are some problems with exsisting features.
Will improve over time.
Translucent and additive materials don't always render corectly in DOWNSHOT 1.4/1.5. Try creating a new material and copying over nodes to possibly fix the issue.
Masked materials don't render in the far right eye. No know fix at the moment. While it causes a performance hit, you can replace masked materials with additive materials to fix the issue.
Menu componets in the world stop updating. Change tick to pre-physics and disable Update When Not Rendered.
Somtimes a mod is compiled with no or little assets. Please reach out to the developer if this happens to you. This issue should be fixed as of v1.4.
Error 101 indicates an error with cooked assets.
Any assets outside of the content folder for your mod are not compiled. This is not a bug. Ensure the only assets you refrence are: In your mod content folder (Content/{YourModName}/, not Content/ ), engine assets, sdk assets. Some default plugin assets will work, this is not always the case.
Using a windows PC, install the Unreal Engine version required for your mod build target version (see above).
Download the SDK version required for your mod build target version (see above)
Create a new unreal project, it can be blank or include starter content. Name the project whatever you like.
In your project directory (standard directory is Documents\Unreal Projects\[YourProject]), create a new folder named "Plugins".
Extract the SDK into your new plugins folder.
See plugin setup for more info on configuring the plugin.
Optional: See "quick development" below for faster development iteration.
To launch the SDK tools window, in the unreal editor's level editor, at the top toolbar click DOWNSHOT SDK -> Launch SDK Tools Window.
Open XR, XR Base, and other XR plugins should be disabled or may cause issues. Please confirm this in plugin settings.
Enter a name, can NOT be changed, that will be used as your mod name.
Hit "configure", then restart.
The "install to game" and "install to HMD" buttons in the SDK tool allow you to directly install your mod to DOWNSHOT.
Install to game will always work as long as DOWNSHOT is downloaded to your PC via the rift store.
Install to HMD is a bit more dificult. You must have ABD settup for your meta quest device, (many tutorials online), then set the "AbdPath" setting in your project's DefaultEngine.ini file. Inside the file, find "[/Script/DOWNSHOT_SDK.Settings]" and type in the location of your adb.exe install, no quotations. If you have sidequest installed, it would most likley be ...\AppData\Roaming\SideQuest\platform-tools\adb.exe. Install to HMD is not fully functional yet, it currently will only work with one mod project at a time. Your engine will manualy need to be restarted after setting the AbdPath setting. A working example in your DefaultEngine.int file would be:
[/Script/DOWNSHOT_SDK.Settings]
ModName=test
SDK_Version=0.11
AdbPath=C:\Users\username\AppData\Roaming\SideQuest\platform-tools\adb.exe
Put all assets in the content folder with the same name as your mod.
Put maps in the map folder or subfolders.
Put spawnables in the spawnables folder or subfolders.
Hit compile to compile the mod to a platform. The first compile will take a while, but all other compiles will be quick because shaders are saved.
Mods are saved in archive folder.
Hit the "create template map" button to create a template map in your mod folder. Use the world settings and light source settings from this map in your other maps. Make sure to rename it!
Upload the compiled zip (for each platform) to modio.
Ensure that you lable your mod with the game version it was compiled for. If you do not do this, players will not be able to download your mod.
Follow all rules for making mods that both mod developers and users agree to upon downloading the SDK or downloading mods.
Be mindfull of performance. Disable tick on actors that don't use it. Keep the scene component count to a minimum. Setup LODs for meshes. Limit use of translucent materials and other complex shaders. Disable overlap and hit events on physics actors that don't need them. Use walls to limit how many actors are in view at once. Use fog to limit how far the user can see. Keep drawl calls as low as possible. Use the built in debug options in DOWNSHOT to test your mod's performance. In general, the better your mod performs the more fun it will be to players.
Keep in mind that in multiplayer, there is not just one instance of an object, but instead it exist on all machines. Blueprint has replicated events, however, inexperienced developers should stick to only making calls to the local player. (Players have ownership over grabbed items, RPCs to server from actors will only work when grabbed).
The host machine has absolute athority, use the "IsServer" pure function in your scripts to run specific logic only on host machine.
Use the template level to see diffrent features of the SDK. Hit the "Create Template Map" button in the SDK Tools window to add the map to your map folder.
Instead of creating a level from scratch, it is recomended to use the blank map as a starting point.
Create an actor within the Spawnables directory of your mod. Use underscores instead of spaces and the game will display spaces at runtime.
The "grab", "pull", and "stab" tags allow for simple interaction and are self explanatory. You can use these as actor tags or for individual mesh components. (It is not recommended to use the "grab" tag on spawnables, it does not allow for multiplayer replicated ownership. Use it on static world objects, like climbing walls).
Use the "NoGrabAlert" tag to ensure no replication logic runs. Add to anything in the world that is grabable but not moveable or controllable.
For moving floors or meshes that are intended to be walked on, you can add the "RelativeGround" tag to bind the player rig rotation and velocity to it. For example, a merry-go-round that the player can walk on. This is make the player rotation and velocity relative to that component. In the case of a non moving component that moves the player by a constant amount, (like the walkway), add the tag "VelocityOverride" and below that tag add a vector, for example, "0,2,-99", this will be the velocity that the player velocity is made relatative to.
To adjust the spawn offset when spawned via the item spawner, use the "SpawnVisualizerOffset" actor tag with another tag containing the vector of the offset, for example, "4,0,-100", directly after in the array. Use the actor tag "SpawnBoxExtentOverride" with a vector after in the array to use a custom overlap check box when spawning. Use the tag "HFV" in any components you do not want to be displayed in the spawn visualizer.
NEW TO v1.5:
Add tag "PersistantPhysicsFlags" to the root static mesh component of an actor if you don't want physics flags like, CCD, Overlap Events, and Hit Events to be enabled/disabled by the game when the player interacts with an actor. For most cases, you do not need to add the tag.
For any spawnable actor, add the ItemManager component to it. This component will set up the spawnable for multiplayer assuming "Replicate" and "ReplicateMovement" are both set to true.
For complex interaction, use the StaticMeshInteraction component for any areas on actors you want to be interactable. It allows for input events and snapping the hand to a position. (For example, use one for the handle of a gun, one for the foregrip, and one for the slider. Use the trigger input event from the handle interaction to fire the gun). Each StaticMeshInteraction should have an attached GrabLocation component. (See the template map items for an example, see below for more info). You can configure physical grab settings and grab permissions via the StaticMeshInteraction. To enable or disable the ability to grab at runtime, call the SetGrabAllowed function and do not set the GrabAllowed variable directly. To know what hand is grabbing, save the IsRight value sent in the grab event. Use the input and button event for interaction. (While it is unrelated to this component, the PlayHapticRumble function in the API is intended to be used alongside interaction components). Set the "IndexFingerFreeMovement" variable to true if you want the index finger to not be locked in a grab position. (Use for guns with triggers).
The GrabLocation componet must always be a child of a StaticMeshInteraction component. This will be the location and rotation of the grab. Because the hands use smart finger positioning, you do not have to alter the finger curl value. If you want to force a specifc grip animation, the figer curl values act as clamps on each finger. (Setting the value of the ring curl to 1 will for the ring finger to close all the way, setting it to 0.5 will force the ring finger to close between 0.5 and 1 depending on what the finger solver calculates).
Use the CollisionEffects component to add collision sound and/or collision damage effects to an actor. Will only work with meshes that have hit events.
Use the Inventory component to allow an item to be stored in the player inventory. The relative offsets can be configured here.
See in-game example
See in-game example
See in-game example
(more info coming soon)
See in-game example
Use the SDK API to read and write data to the core game instance. For ease of use and stablility, it is written in the blueprint scripting language. You can make funciton calls in any blueprint object, commonly used ones include Actors, Scene Components, Level Blueprints, and so on.
The SDK function library will expand with time, functions will be documented here.
AddDamageToActor - Use this to add damage to any replicated shell, local player, or enemies.
AddPlayerDamage - Damages the local player. World impulse is not needed.
AddPlayerVelocity - Adds to the local player's velocity in world space.
GetActorNetOwnership - Tries to get the owning pawn of an actor. When an actor is held by a player, that player owns the actor and has authority over its transform and can make RPCs.
GetCameraTransform - Gets the camera transform in world space.
GetGrabbedActor - Attempts to get the actor that a hand is grabbing.
GetHandTransform - Gets the hand transforms in world space.
GetPlayerActors - Useful for checking if something collided with the player. Body is the core player rig. Left and right hands are the separate hand actors. Replicated shell is the version of the player seen on all other clients.
GetDirectionalValues - This is the internal velocity values of the player. The same values are used in animation and are affected by relative ground objects. They are rotated relative to player orientation.
GetLocomotionSphere - Gets the sphere that rolls around on the ground for player movement. Could be used to move the player around. This is not the root component.
GetPlayerWorldLocation - Gets the location of the local player, at the player's feet center.
GetPlayerWorldVelocity - Gets the player's world space velocity.
GrabActor - Tries to grab an actor with a hand.
Log - Record a string of text to the log, readable via the debug menu.
Open Level - Opens a level, using screen fade transition and replicated travel.
Game path ex: Game/{YourModName}/map1
Absolute path ex: c:/user/projects/unreal/mymod/Content/{YourModName}/map1.umap
Must be called from server.
PlayHapticRumble - Plays a haptic effect for a hand.
ReleaseHand - Tries to release anything a hand is grabbing.
SetActorPlayerCollision - Enables/disables the collision of all meshes in an actor with the player's body. Hand collision will not be affected.
SetGrabAllowed - Enables/disables grabbing for an SMInteraction.
SetHardwareOcclusion - DO NOT USE UNLESS YOU KNOW WHAT YOU ARE DOING. When enabled, casues meshes blocked from view to not be rendered. It has a large hit on performance and should almost never be used. The only DOWNSHOT map to use this is prop hunt, where many non-static meshes need to be culled. Reset to false every time a level is opened.
SetPlayerScale - Sets the scale of the local player.
SetReverbLevel - Values between 0-3 inclusive are valid. 0 is none, 3 is the most. Reset to default when new level loaded.
TeleportPlayer - Teleports the player. Collision will not occur with objects between teleportation.