Update Code Docs
This commit is contained in:
parent
bd65c6c24d
commit
25805d40e5
41 changed files with 10977 additions and 2287 deletions
31
sites/codesnippets/AlyxGrab.qmd
Normal file
31
sites/codesnippets/AlyxGrab.qmd
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
title: "Alyx Grab"
|
||||
---
|
||||
In Class: `BP_TraceController` | Based on VREs BP_TeleportTrace
|
||||
|
||||
To make grabbing more comfortable and accessible, I implemented a pull-grab mechanic inspired by Half Life Alyx. While the VR Expansion Plugin already implements logic for tossing objects towards the player, the template and many other resources rely on a line trace to get the object to toss. This results in multiple problems, above all the player having to aim very precisely and objects blocking each other.
|
||||
|
||||
To target these issues, I use a multi sphere trace to get all actors in range, saving them to an array. For each, we can check their angle to the hand via the dot product between the hand->forward and hand->object vectors and save them to an array as well. By getting the min of the of the dot product array, we can retrieve the correct object via the index (could've also used a map).
|
||||
|
||||
|
||||
Function: `Trace For Tossable Objects`
|
||||
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/3xy3o_ve/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
|
||||
Function: `Get Angle To Hand`
|
||||
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/o_fr6mlk/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
|
||||
The trace relies on its own collision channel named TossableTrace, allowing for objects like cabinet doors to block this specific trace. As this blocks access to compartments smaller than the trace, there is a second smaller trace doing the same job (only if larger trace is blocked, might be further optimizable).
|
||||
|
||||
As it might not favorable for all components on the actor to be tossable, the Item Data Component (originally introduced for the [Inventory]()) holds an array of primitive components which are quickly added via a library macro on the respective actor (you can't choose primitive components via the dropdown on the component).
|
||||
|
||||
The ribbon between the object and the hand is drawn via a Niagara System getting passed an array of locations.
|
||||
While I was aware of this technique from how the default UE5 VR Template renders its teleport-preview, there is also a [writeup by Steve Streeting](https://www.stevestreeting.com/2025/01/09/niagara-particles-setting-positions-manually/) if you need further information.
|
||||
|
||||
Note: The toss from VRE needs "Simulation Generates Hit Events" enabled to work correctly.
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Code"
|
||||
title: "Captcha Door"
|
||||
---
|
||||
Example for BlueprintUE
|
||||
|
||||
13
sites/codesnippets/CustomAIController.qmd
Normal file
13
sites/codesnippets/CustomAIController.qmd
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: "Follow Spline / AIController"
|
||||
---
|
||||
In Class: `CustomAIController`
|
||||
|
||||
While Navigation builds on the UE AI Controller / Character Movement with NavMeshes, I wanted to implement a more precise way to control the path a NPC takes. Turns out, Unreal doesn't seem to have a "Follow Spline" logic inbuilt, which I found to be a bit trickier than expected. It's currently based of [this Tutorial](https://www.youtube.com/watch?v=UIF1PcmZkGA), which calculates a speed factor from Max Walk Speed and Spline Length and then continuously moves the Actor to the new Point along the Spline at that Value. Adding Jump functionality with this approach added extra complexity as the timeline needs to stop at the correct distance from the Character for the AI not to get confused.
|
||||
|
||||
|
||||
|
||||
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/-azlwrm2/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
18
sites/codesnippets/GripRobot.qmd
Normal file
18
sites/codesnippets/GripRobot.qmd
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: "Clarice / Grippable Robot"
|
||||
---
|
||||
What. A. Pain.
|
||||
|
||||
In Class: `BP_Clarice`
|
||||
|
||||
For the main NPC that guides the player - Clarice - I wanted a high degree of interactability. This involves grabbing the robot, e.g. to throw them somewhere to solve riddles, use them as a key or other shenanigans. I also wanted them to be rather flexible when it comes to locomotion (Walk / Fly / Jump / Roll) for it to able to follow the player anywhere.
|
||||
|
||||
Here are some learning from implementing:
|
||||
- Your characters Physics Asset NEEDS a root body when scaled. I personally still struggle with Physics Assets.
|
||||
-
|
||||
|
||||
|
||||
::: {.callout-note}
|
||||
## Thank you
|
||||
A big thank you to Joshua "MordenTral" Statzer (Developer of the VREP) who took personal time to look into my issues with grabbing Skeletal Meshes. The first and only time someone helped me out personally in this project, and also doing so in their free time.
|
||||
:::
|
||||
13
sites/codesnippets/Inventory.qmd
Normal file
13
sites/codesnippets/Inventory.qmd
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: "Inventory"
|
||||
---
|
||||
|
||||
The Inventory uses a scalable, circular array of widget components the user can put objects in and draw objects out. When the inventory is opened, the player moves their hand towards a widget, which then gets activated. Depending of the content of the widget and content of the hand, an action (put in, pull out, replace) is triggered on inventory close. Compared to [approaches based on a line trace/widget interactor](https://www.youtube.com/watch?v=YE0sfJyraws), I use the distance to the hand for a quicker and "sloppier" interaction.
|
||||
|
||||
Item Data is handled via an Item Data Component, following the guidance of [Ryan Laleys Inventory System Tutorial Series](https://www.youtube.com/watch?v=vHT4MhmwacE&list=PL4G2bSPE_8umjCYXbq0v5IoV-Wi_WAxC3&index=1). The Item Data is drawn from a Data Table.
|
||||
|
||||
|
||||
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/-azlwrm2/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
18
sites/codesnippets/MainMenu.qmd
Normal file
18
sites/codesnippets/MainMenu.qmd
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: "Main Menu"
|
||||
---
|
||||
In Class: `BP_MainMenu`
|
||||
|
||||
The main menu is composed of several widget components in 3D-Space. The Widget Index defines the depth of the menu, e.g. the widget showing the Audio Settings Widget is accessed from Settings (from Main at Index 0) -> Audio (from Settings at Index -1) -> Audio Widget (at Index -2). Opening a new Menu causes all Widget Indices to increment. Widget with an Index lower than 0 gets collapsed, Widgets with an Index greater 0 get disabled and only at Index 0, the Widget is enabled. On disabled widgets, the last pressed button is altered visually which also gets reset at Index 0.
|
||||
|
||||
All Widget Buttons inherit from the same widget class implementing an enum to save the button function. The button actions are centralized by binding to a custom event dispatcher on the click event, passing the enum to the BP_MainMenu. From there, we can switch on enum and handle the respective functionality. The main thing we need to do manually is running the UpdateIndices Function to increment and making the correct Widget visible (we can't do this automatically as there are multiple Widgets with the same Index).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/-azlwrm2/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
30
sites/codesnippets/MovablesSoundComponent.qmd
Normal file
30
sites/codesnippets/MovablesSoundComponent.qmd
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
title: "Movables Sound Component"
|
||||
---
|
||||
In Class: `MovablesSoundComponent`
|
||||
|
||||
This Component is an Actor Component to designed to be attached to Actors that generate Sounds based on their physical movement. This includes standalone objects like a ball or components like drawers in cabinet.
|
||||
|
||||
|
||||
**Detecting Hit and Slide Movements**
|
||||
|
||||
When one object hit another, we expect it to make some kind of hit sound, depending on their qualities (size, material, surface texture etc.) and the hit velocity. A special case is dragging an object across a surface. Although this causes repetitive hits, we don't expect the Hit Sound to be played repetitively but a dedicated "slide sound".
|
||||
To check wether a Hit Event from the simulation should trigger a Hit Sound or a Slide Sound, we can use the velocity vector of the hit component and compare it to to the Hit Normal Vector. When we slide across a surface, the velocity is perpendicular to the impact normal. Using acosd, you can convert the dot product to an angle, which can be easier to work with. Based on an Angle Threshold, you can decide whether a slide should be considered a slide.
|
||||
|
||||
|
||||
::: {.callout-note}
|
||||
## A thought
|
||||
Now that I'm writing it down, you could also make the Threshold depending on the velocity, resulting in slow movements to be more susceptible to "clonks".
|
||||
:::
|
||||
|
||||
|
||||
**Infinite Loops**
|
||||
|
||||
Creating slide sounds involves looping sounds without noticeable repeats. There are several ways to create looping sounds from non-looping sounds. For the DAW [Reaper](https://www.reaper.fm/) that I use for everything audio-related features, there is a helpful [script by X-Raym](https://www.youtube.com/watch?v=yjGDW4wVkEQ) available that automates this process from a time selection.
|
||||
|
||||
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/a6syaqcp/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
|
||||
|
||||
18
sites/codesnippets/SaveGame_SPUD.qmd
Normal file
18
sites/codesnippets/SaveGame_SPUD.qmd
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: "SPUD / Save Games"
|
||||
---
|
||||
|
||||
To handle SaveGames and Persistence in Level Streaming, [SPUD](https://github.com/sinbad/SPUD/issues) is used.
|
||||
The WB_CustomSaveLoadScreen used in the [Main Menu]() is largely based of the [SPUD Examples](https://github.com/sinbad/SPUDExamples) SaveLoadScreen Widget.
|
||||
|
||||
Most Variables are passed to the GameInstance, which is especially important for variables that need to exist before the game is loaded, e.g. on the initial Main Menu Map.
|
||||
|
||||
::: {.callout-note}
|
||||
## Note
|
||||
Saving the GameInstance with SPUD via BP should've been be very straight forward, but I was stuck there for multiple days. Eventually I opened up a [Github-Issue](https://github.com/sinbad/SPUD/issues/139) and it was confirmed that the SPUD Subsystem is not ready on Event Init of the BP GameInstance. I went on implementing going the C++ way, [but a delay until the Subsystem is ready should fix that](https://github.com/sinbad/SPUD/commit/416122438c33f1f7d77d0c319876bf763e58db33).
|
||||
:::
|
||||
|
||||
|
||||
Pulling Actors into the persistent Levels
|
||||
|
||||
As a lot objects in VR are interactible and can therefore easily be moved by the player, it's possible that movable objects leave their streaming level boundary and get despawned when their owning level is unloaded. We have to possibilities to fix that: Having all those objects on the persistent level by default, which isn't ideal from an optimization perspective, or move them to the persistent level when the player actually interacts with them. From my knowledge, there is no *proper* way of changing the owning level at runtime but destroying and respawning the actor, which isn't always ideal.
|
||||
29
sites/codesnippets/Slicegame.qmd
Normal file
29
sites/codesnippets/Slicegame.qmd
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
title: "Slicegame"
|
||||
lightbox: true
|
||||
---
|
||||
---
|
||||
|
||||
The Slicegame is my attempt at implementing a [Beatsaber](https://beatsaber.com/)-Style Rhythm-Game. It explores Unreals Harmonix Plugin for parsing Midi in Metasounds and Geometry Script for real time boolean operations.
|
||||
|
||||
Given a Midi File, the system in `BP_DynamicObjectSpawner` spawns instances from the class `BP_DynamicHitObject` (the thing you want to hit) on a 3x3 Grid, moves them towards a location over time so it's always at to correct location (PlayerPosition + ArmLength) on the beat. The Midi also encodes from which direction the HitObject should be hit which saved in an Enum in the class during spawn.
|
||||
|
||||

|
||||
|
||||
|
||||
Correct Hit detection to me several approaches, its a bit tricky because while our objects (or rather their hit indictors) don't move relative to the character, their angle to the player does change when the objects move from front to back while the player forwards or sideways. The hit detection therefore needs to take the characters view vector into account. From there, you can create up and right vectors and compare them direction of the sword via the dot product.
|
||||
|
||||
In Class : `BP_DynamicHitObject` | Function: `GetHitType`
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/kxu6x76k/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
|
||||
As both velocity (sword is wiggly) and impact normal (surface doesn't always point in hit direction) vectors you can get from the hit event turned out to be rather unreliable for detection sword direction, I went with sampling the impact point on hit, attaching that point to the sword by converting the location into the relative space of the sword. After a short delay, that point, virtually attached to sword, has moved. By converting that point back to world transform, we can calculate the direction by subtracting hit location and delay sampled location. This works quite reliably.
|
||||
|
||||
|
||||
In Class : `BP_DynamicHitObject`
|
||||
```{=html}
|
||||
<iframe width="100%" height="500" src="https://blueprintue.com/render/1g36zapg/" scrolling="no" allowfullscreen></iframe>
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -3,14 +3,14 @@ title: "Project Setup"
|
|||
---
|
||||
If you want to take a look inside a project, there are currently three important repositories:
|
||||
|
||||
- VIRTUOS_Playground: The repository contains the Unreal Engine Project
|
||||
- VIRTUOS_Assets: Contains all Project related assets like 3D-Models, Graphics etc.
|
||||
- VIRTUOS_Documents: Contains all written Documents
|
||||
- VIRTUOS_Docs: The Documentation in QUarto (which you're reading right now)
|
||||
- [VIRTUOS_Playground](https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Playground): The repository contains the Unreal Engine Project
|
||||
- [VIRTUOS_Assets](https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Assets): Contains all Project related assets like 3D-Models, Graphics etc.
|
||||
- [VIRTUOS_Documents](https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Documents): Contains all written Documents
|
||||
- [VIRTUOS_Docs](https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Docs): The Documentation of this Project (which you're reading right now)
|
||||
|
||||
# Setting up the project with UE5
|
||||
|
||||
If you're familiar with Git, you'll likely already know how to get the files.
|
||||
If you're familiar with Git, you'll likely already know how to get the files from the repository:
|
||||
|
||||
```bash
|
||||
git pull https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Docs.git
|
||||
|
|
@ -22,7 +22,7 @@ Hit `File -> Clone repository`
|
|||
|
||||

|
||||
|
||||
Enter the repository from `code.virtuos.world` you want to clone, e.g. https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Playground.git
|
||||
Enter the repository from `code.virtuos.world` you want to clone, e.g. <https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Playground.git>
|
||||
|
||||

|
||||
|
||||
|
|
@ -31,20 +31,22 @@ Enter the repository from `code.virtuos.world` you want to clone, e.g. https://c
|
|||
|
||||
The project uses the following external Plugins:
|
||||
|
||||
- VR Expansion Plugin, see https://github.com/mordentral/VRExpansionPlugin
|
||||
- SPUD: Steve's Persistent Unreal Data library, see https://github.com/sinbad/SPUD
|
||||
- [VR Expansion Plugin](https://github.com/mordentral/VRExpansionPlugin)
|
||||
- [SPUD: Steve's Persistent Unreal Data library](https://github.com/sinbad/SPUD)
|
||||
- [SUDS: Steve's Unreal Dialogue System](https://github.com/sinbad/SUDS)
|
||||
- [StevesUEHelpers: Steve's UE Helper Plugin Library](https://github.com/sinbad/StevesUEHelpers)
|
||||
|
||||
The Plugins are already in the /Plugins folder
|
||||
|
||||
The Plugins are already in the /Plugins folder and should build with the project without errors. For manual installation, see the respective Documentation.
|
||||
|
||||
# Building the project
|
||||
|
||||
Note: To build the project, you'll need Visual Studio installed on your system.
|
||||
|
||||
To build the project, you'll need Visual Studio installed on your system.
|
||||
|
||||
<ol>
|
||||
<li>Right click the .uproject file and hit `Generate Visual Studio project files`. </li>
|
||||
<li>Open the newly generated .sln file in Visual Studio. From there, hit `Build -> Build solution`.</li>
|
||||
</ol>
|
||||
|
||||
|
||||
Note: This may take a while.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Websevices"
|
||||
title: "Webservices"
|
||||
---
|
||||
# Forgejo
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ sudo docker-compose up -d
|
|||
|
||||
- To redirect the homepage to the repository view:
|
||||
|
||||
```nginx
|
||||
```bash
|
||||
server {
|
||||
server_name code.virtuos.world;
|
||||
|
||||
|
|
@ -311,21 +311,10 @@ Wordpress updates itself. Plugins may need manual updating via the Wordpress Int
|
|||
|
||||
---
|
||||
|
||||
# Wiki.js
|
||||
|
||||
Wiki.js was dumped in favour of Quarto.
|
||||
# Quarto
|
||||
|
||||
Wiki.js is an open source Wiki software. The Wiki.js instance is hosted on Uberspace.de and you are currently accessing it on [https://docs.virtuos.world](https://docs.virtuos.world).
|
||||
|
||||
## Installation on Uberspace
|
||||
|
||||
The Wiki.js installation is well documented on
|
||||
[https://lab.uberspace.de/guide_wiki-js/](https://lab.uberspace.de/guide_wiki-js/)
|
||||
|
||||
## Updating Wiki.js
|
||||
|
||||
An update script is available at the same location:
|
||||
[https://lab.uberspace.de/guide_wiki-js/](https://lab.uberspace.de/guide_wiki-js/)
|
||||
I switched from Wiki.js to Quarto, a static site generator. All files are in [this repository](https://code.virtuos.world/VIRTUOS_WORLD/VIRTUOS_Docs).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -334,7 +323,22 @@ An update script is available at the same location:
|
|||
Pretix is an open source ticketing system. It's currently not in use. This installation is not as easy, but well documented here:
|
||||
[https://docs.pretix.eu/en/latest/admin/installation/docker_smallscale.html](https://docs.pretix.eu/en/latest/admin/installation/docker_smallscale.html)
|
||||
|
||||
---
|
||||
|
||||
# BlueprintUE
|
||||
|
||||
I failed to host BlueprintUE multiple times (I don't know.=). I gave up and use the official page at https://blueprintue.com/profile/waldo/.
|
||||
I failed to host BlueprintUE multiple times (I don't know uwu). I gave up and use the official page at https://blueprintue.com/profile/waldo/.
|
||||
|
||||
---
|
||||
|
||||
~~# Wiki.js~~
|
||||
|
||||
~~Wiki.js is an open source Wiki software. The Wiki.js instance is hosted on Uberspace.de and you are currently accessing it on [https://docs.virtuos.world](https://docs.virtuos.world).~~
|
||||
|
||||
~~## Installation on Uberspace~~
|
||||
|
||||
~~The Wiki.js installation is well documented on [https://lab.uberspace.de/guide_wiki-js/](https://lab.uberspace.de/guide_wiki-js/)~~
|
||||
|
||||
~~## Updating Wiki.js~~
|
||||
|
||||
~~An update script is available at the same location: [https://lab.uberspace.de/guide_wiki-js/](https://lab.uberspace.de/guide_wiki-js/)~~
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue