Created by developers, for developers. U3D aims to give you the tools you need to stand up your game quickly, then experiment with and iterate on your game's design.
No royalties, no fees, no obligations, no strings attached. All the power to you and your team.
U3D and it's cross-platform suite of tools put the power to create stunning experiences at your fingertips. Visually create and manage scenes, materials and terrains.
Import files from any Digital Content Creation tool using industry standards such as FBX, DAE and glTF, as well as community favorites like MD5, IQM and MD3.
Bandwidth, latency, and packet loss are primary concerns among anyone looking to make a multiplayer games. Built on top of SLikeNet (RakNet), U3D gives you the power to create robust simulations.
Build with AngelScript and Lua. The built-in editor is powered by AngelScript, allowing you to easily customize your workflow. Native code is only used for low-level modules like rendering, physics and sound.
The character controller physics of the Quake 3 Arena game engine are responsible for handling the movement and collision detection of the player character. These physics are designed to simulate the movement of a first-person shooter (FPS) character in a 3D environment, and are based on a combination of kinematic and dynamic physics.
Some of the key features of the Quake 3 Arena character controller physics include:
The character controller physics in Quake 3 Arena are designed to create a fast-paced and dynamic gameplay experience. The physics allow the player to perform a variety of movement techniques such as bunny hopping, strafe jumping and circle strafing, which is a set of techniques that allows players to move and dodge in a very fast and precise way. Overall, the character controller physics of the Quake 3 Arena game engine are designed to provide a smooth and responsive movement for the player character, allowing them to navigate the game world and interact with the environment in a believable and realistic way.
Here is a tutorial on how to create an U3D game with a playable first-person character and first-person camera, using the Quake 3 character movement physics:
Create the physics world and character controller
#include <Urho3D/Urho3D.h>
#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Engine/Application.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/Physics/PhysicsWorld.h>
#include <Urho3D/Physics/RigidBody.h>
#include <Urho3D/Physics/CollisionShape.h>
#include <Urho3D/Physics/KinematicCharacterController.h>
using namespace Urho3D;
class MyApp : public Application
{
public:
MyApp(Context* context) : Application(context)
{
}
virtual void Start()
{
// Create the scene
Scene* scene = new Scene(context_);
// Create a physics world component
PhysicsWorld* physicsWorld = scene->CreateComponent<PhysicsWorld>();
// Create a character controller component
CharacterController* characterController = scene->CreateComponent<CharacterController>();
}
virtual void Setup()
{
engineParameters_["FullScreen"] = false;
engineParameters_["WindowWidth"] = 1280;
engineParameters_["WindowHeight"] = 720;
}
};
class CharacterController : public Component
{
public:
CharacterController(Context* context) : Component(context)
{
}
void Start() override
{
// Create a capsule collision shape for the character
CollisionShape* shape = node_->CreateComponent<CapsuleCollisionShape>();
shape->SetSize(Vector3(0.5f, 1.0f, 0.5f));
// Create a rigid body for the character
RigidBody* body = node_->CreateComponent<RigidBody>();
body->SetMass(80.0f);
body->SetCollisionShape(shape);
// Create a kinematic character controller
kinematicCharacterController_ = node_->CreateComponent<KinematicCharacterController>();
kinematicCharacterController_->SetRigidBody(body);
kinematicCharacterController_->SetCollisionShape(shape);
kinematicCharacterController_->SetMaxStepHeight(0.5f);
}
private:
KinematicCharacterController* kinematicCharacterController_;
};
In this code, a new CharacterController component is created and added to the scene in the Application class's Start() function. In the Start() function of the component, a capsule collision shape is created and set to the character's rigid body, and a KinematicCharacterController component is created and set to the character's collision shape. The max step height, which is the maximum height that the character can step up, is set to 0.5f.
Add the character's movement controls
class CharacterController : public Component
{
public:
CharacterController(Context* context) : Component(context)
{
}
void Start() override
{
//... previous code for collision shape, rigid body and kinematic character controller
}
void Update(float timeStep) override
{
Input* input = GetSubsystem<Input>();
// Get the move direction from the input
Vector3 moveDirection = Vector3::ZERO;
if (input->GetKeyDown(KEY_W))
moveDirection += Vector3::FORWARD;
if (input->GetKeyDown(KEY_S))
moveDirection += Vector3::BACK;
if (input->GetKeyDown(KEY_A))
moveDirection += Vector3::LEFT;
if (input->GetKeyDown(KEY_D))
moveDirection += Vector3::RIGHT;
// Normalize the move direction
moveDirection.Normalize();
// Use the kinematic character controller's Move function to update the character's position based on the move direction and time step
kinematicCharacterController_->Move(moveDirection * timeStep);
}
private:
KinematicCharacterController* kinematicCharacterController_;
};
In this code, the Update function gets the move direction from the input and normalizes it to ensure that the character moves at a consistent speed. The kinematic character controller's Move function is called and passed the move direction multiplied by the time step. This moves the character's position based on the move direction and time step.
It is important to note that the move function of the kinematic character controller uses the character's collision shape and the collision information from the physics world to move the character. This way, the character will respond correctly to collisions with the environment.
Add the first-person camera
// Create a camera component and set it as the viewport's camera
camera_ = GetScene()->CreateChild("Camera")->CreateComponent<Camera>();
GetSubsystem<Renderer>()->SetViewport(0, new Viewport(context_, GetScene(), camera_));
// Position the camera at the character's head
camera_->SetPosition(node_->GetPosition() + Vector3(0.0f, 1.0f, 0.0f));
// Point the camera in the same direction as the character's forward vector
camera_->SetDirection(node_->GetDirection());
// Set the camera's near clip distance
camera_->SetNearClip(0.1f);
// Set the camera's far clip distance
camera_->SetFarClip(100.0f);
Set up the input handling for the camera and character
virtual void Start()
{
//... previous code for creating the scene, physics world, and character controller
// Subscribe to the key down event to handle character movement
SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(MyApp, HandleKeyDown));
// Subscribe to the mouse move event to handle camera movement
SubscribeToEvent(E_MOUSEMOVE, URHO3D_HANDLER(MyApp, HandleMouseMove));
// Subscribe to the mouse button down event to handle mouse inputs
SubscribeToEvent(E_MOUSEBUTTONDOWN, URHO3D_HANDLER(MyApp, HandleMouseButtonDown));
}
void HandleKeyDown(StringHash eventType, VariantMap& eventData)
{
using namespace KeyDown;
int key = eventData[P_KEY].GetInt();
// Send the key down event to the character controller
characterController_->HandleKeyDown(key);
}
void HandleMouseMove(StringHash eventType, VariantMap& eventData)
{
using namespace MouseMove;
int dx = eventData[P_DX].GetInt();
int dy = eventData[P_DY].GetInt();
// Send the mouse move event to the camera component
camera_->HandleMouseMove(dx, dy);
}
void HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
{
using namespace MouseButtonDown;
int button = eventData[P_BUTTON].GetInt();
// Send the mouse button down event to the camera component
camera_->HandleMouseButtonDown(button);
}
Add collision shape for the environment, if you want to be able to walk around.
// Get the root node of the scene
Node* rootNode = GetScene()->GetChild("Environment", true);
// Create a collision shape for the environment
CollisionShape* environmentShape = rootNode->CreateComponent<CollisionShape>();
//... previous code for setting the shape and size of the collision shape
// Get the rigid body of the environment
RigidBody* environmentBody = rootNode->GetComponent<RigidBody>();
// Set the physics properties of the environment
environmentBody->SetFriction(0.8f);
environmentBody->SetRestitution(0.1f);
environmentBody->SetRollingFriction(0.1f);
environmentBody->SetAnisotropicFriction(Vector3(1.0f, 1.0f, 1.0f));
With this tutorial, you have the basic structure for a first-person game with a playable character using Quake3 physics in U3D. You can add more features such as jumping, crouching, shooting, and more by adding more functionality to the CharacterController and the environment.
Inverse Kinematics (IK) is a technique used in game engines and animation software to control the movement of a character's joints in a more realistic...