feat: npc follow logic
This commit is contained in:
parent
411f1662c1
commit
1e94542085
14 changed files with 268 additions and 11 deletions
|
|
@ -13,10 +13,12 @@ void Character::_bind_methods() {
|
||||||
void Character::physics_process(double delta) {
|
void Character::physics_process(double delta) {
|
||||||
Vector3 const velocity{ get_velocity() };
|
Vector3 const velocity{ get_velocity() };
|
||||||
Vector3 new_velocity{ velocity };
|
Vector3 new_velocity{ velocity };
|
||||||
new_velocity.x = this->world_movement_direction.x * this->data->get_speed();
|
new_velocity.x = this->world_movement_direction.x;
|
||||||
new_velocity.z = this->world_movement_direction.y * this->data->get_speed();
|
new_velocity.z = this->world_movement_direction.y;
|
||||||
set_velocity(new_velocity);
|
set_velocity(new_velocity);
|
||||||
|
if (!velocity.is_zero_approx()) {
|
||||||
move_and_slide();
|
move_and_slide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::_notification(int what) {
|
void Character::_notification(int what) {
|
||||||
|
|
@ -35,6 +37,14 @@ void Character::_notification(int what) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PackedStringArray Character::get_configuration_warnings() const {
|
||||||
|
PackedStringArray warnings{ super_type::get_configuration_warnings() };
|
||||||
|
if (this->data.is_null()) {
|
||||||
|
warnings.push_back("Character requires 'data' to be initialised. To avoid crashes consider adding a placeholder if you intend to programmatically initialise it.");
|
||||||
|
}
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
|
||||||
void Character::set_movement(Vector2 movement) {
|
void Character::set_movement(Vector2 movement) {
|
||||||
this->world_movement_direction = movement;
|
this->world_movement_direction = movement;
|
||||||
}
|
}
|
||||||
|
|
@ -56,15 +66,24 @@ void CharacterState::_notification(int what) {
|
||||||
return;
|
return;
|
||||||
case NOTIFICATION_ENTER_TREE:
|
case NOTIFICATION_ENTER_TREE:
|
||||||
this->character = cast_to<Character>(get_parent());
|
this->character = cast_to<Character>(get_parent());
|
||||||
|
ERR_FAIL_COND_EDMSG(this->character == nullptr, "CharacterState requires parent to be of type Character");
|
||||||
return;
|
return;
|
||||||
case NOTIFICATION_READY:
|
case NOTIFICATION_READY:
|
||||||
if (start_active) {
|
if (start_active) {
|
||||||
set_state_active(true);
|
callable_mp(this, &self_type::set_state_active).call_deferred(true);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PackedStringArray CharacterState::get_configuration_warnings() const {
|
||||||
|
PackedStringArray warnings{ super_type::get_configuration_warnings() };
|
||||||
|
if (cast_to<Character>(get_parent()) == nullptr) {
|
||||||
|
warnings.push_back("CharacterState requires direct Character parent");
|
||||||
|
}
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
|
||||||
void CharacterState::switch_to_state(String value) {
|
void CharacterState::switch_to_state(String value) {
|
||||||
if (!this->state_active) {
|
if (!this->state_active) {
|
||||||
print_error(vformat("Attempt to switch from inactive state %s to new state %s", get_path(), value));
|
print_error(vformat("Attempt to switch from inactive state %s to new state %s", get_path(), value));
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
void physics_process(double delta);
|
void physics_process(double delta);
|
||||||
void _notification(int what);
|
void _notification(int what);
|
||||||
|
PackedStringArray get_configuration_warnings() const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_movement(Vector2 movement);
|
void set_movement(Vector2 movement);
|
||||||
|
|
@ -42,6 +43,7 @@ class CharacterState : public Node {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int what);
|
void _notification(int what);
|
||||||
|
PackedStringArray get_configuration_warnings() const override;
|
||||||
void switch_to_state(String state);
|
void switch_to_state(String state);
|
||||||
void stack_state_dependent(String state);
|
void stack_state_dependent(String state);
|
||||||
void notify_dependent_inactive(CharacterState *dependent);
|
void notify_dependent_inactive(CharacterState *dependent);
|
||||||
|
|
|
||||||
13
modules/authority/nav_marker.cpp
Normal file
13
modules/authority/nav_marker.cpp
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "nav_marker.h"
|
||||||
|
|
||||||
|
void NavMarker::_bind_methods() {}
|
||||||
|
|
||||||
|
void NavMarker::_notification(int what) {
|
||||||
|
switch (what) {
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_ENTER_TREE:
|
||||||
|
this->set_gizmo_extents(3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
modules/authority/nav_marker.h
Normal file
19
modules/authority/nav_marker.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "authority/macros.h"
|
||||||
|
#include "scene/3d/marker_3d.h"
|
||||||
|
class Character;
|
||||||
|
|
||||||
|
class NavMarker : public Marker3D {
|
||||||
|
GDCLASS(NavMarker, Marker3D);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int what);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Character *claimed{ nullptr };
|
||||||
|
|
||||||
|
public:
|
||||||
|
GET_SET_FNS(Character *, claimed);
|
||||||
|
};
|
||||||
84
modules/authority/party_member_states.cpp
Normal file
84
modules/authority/party_member_states.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "party_member_states.h"
|
||||||
|
#include "authority/nav_marker.h"
|
||||||
|
#include "authority/player_character.h"
|
||||||
|
#include "core/config/engine.h"
|
||||||
|
#include "core/error/error_macros.h"
|
||||||
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
|
void PartyMemberFollow::_bind_methods() {}
|
||||||
|
|
||||||
|
void PartyMemberFollow::process_position_target() {
|
||||||
|
Vector3 const marker_position{ this->claimed_marker->get_global_position() };
|
||||||
|
Vector3 const nav_target{ this->nav->get_target_position() };
|
||||||
|
Vector3 const global_position{ get_character()->get_global_position() };
|
||||||
|
if (global_position.distance_squared_to(marker_position) < 0.5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (nav_target.distance_squared_to(marker_position) > 0.25) {
|
||||||
|
this->nav->set_target_position(marker_position);
|
||||||
|
}
|
||||||
|
if (this->nav->is_navigation_finished()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Vector3 velocity{ global_position.direction_to(this->nav->get_next_path_position()) };
|
||||||
|
velocity.y = 0;
|
||||||
|
if (this->nav->get_avoidance_enabled()) {
|
||||||
|
this->nav->set_velocity(velocity * get_character()->get_data()->get_speed());
|
||||||
|
} else {
|
||||||
|
push_movement_direction(velocity * get_character()->get_data()->get_speed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PartyMemberFollow::push_movement_direction(Vector3 velocity) {
|
||||||
|
get_character()->set_movement(Vector2{ velocity.x, velocity.z });
|
||||||
|
}
|
||||||
|
|
||||||
|
void PartyMemberFollow::_notification(int what) {
|
||||||
|
if (Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (what) {
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_READY:
|
||||||
|
this->nav = cast_to<NavigationAgent3D>(get_parent()->get_node(NodePath("%NavigationAgent3D")));
|
||||||
|
ERR_FAIL_COND_EDMSG(this->nav == nullptr, "PartyMemberFollow cannot initialise without a navigation agent");
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_PROCESS:
|
||||||
|
process_position_target();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PackedStringArray PartyMemberFollow::get_configuration_warnings() const {
|
||||||
|
PackedStringArray warnings{ super_type::get_configuration_warnings() };
|
||||||
|
if (!get_parent()->has_node(NodePath("%NavigationAgent3D")) || !cast_to<NavigationAgent3D>(get_parent()->get_node(NodePath("%NavigationAgent3D")))) {
|
||||||
|
warnings.push_back("PartyMemberFollow expects a scene sibling of type NavigationAgent3D named with unique name '%NavigationAgent3D'");
|
||||||
|
}
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PartyMemberFollow::state_entered() {
|
||||||
|
Vector<NavMarker *> const &markers{ PlayerCharacter::get_singleton()->get_party_follow_markers() };
|
||||||
|
for (NavMarker *marker : markers) {
|
||||||
|
if (marker->get_claimed() == nullptr) {
|
||||||
|
marker->set_claimed(get_character());
|
||||||
|
this->claimed_marker = marker;
|
||||||
|
if (this->nav->get_avoidance_enabled()) {
|
||||||
|
this->nav->connect("velocity_computed", callable_mp(this, &self_type::push_movement_direction));
|
||||||
|
}
|
||||||
|
set_process(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ERR_FAIL_EDMSG("PartyMemberFollow could not find an unclaimed player follow marker");
|
||||||
|
set_state_active(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PartyMemberFollow::state_exited() {
|
||||||
|
if (this->claimed_marker) {
|
||||||
|
this->claimed_marker->set_claimed(nullptr);
|
||||||
|
this->nav->disconnect("velocity_computed", callable_mp(this, &self_type::push_movement_direction));
|
||||||
|
set_process(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
modules/authority/party_member_states.h
Normal file
22
modules/authority/party_member_states.h
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "authority/character.h"
|
||||||
|
#include "authority/nav_marker.h"
|
||||||
|
#include "scene/3d/navigation/navigation_agent_3d.h"
|
||||||
|
|
||||||
|
class PartyMemberFollow : public CharacterState {
|
||||||
|
GDCLASS(PartyMemberFollow, CharacterState);
|
||||||
|
static void _bind_methods();
|
||||||
|
void process_position_target();
|
||||||
|
void push_movement_direction(Vector3 velocity);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int what);
|
||||||
|
PackedStringArray get_configuration_warnings() const override;
|
||||||
|
void state_entered() override;
|
||||||
|
void state_exited() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NavigationAgent3D *nav{ nullptr };
|
||||||
|
NavMarker *claimed_marker{ nullptr };
|
||||||
|
};
|
||||||
8
modules/authority/player_camera.h
Normal file
8
modules/authority/player_camera.h
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "scene/3d/camera_3d.h"
|
||||||
|
|
||||||
|
class PlayerCamera : public Camera3D {
|
||||||
|
GDCLASS(PlayerCamera, Camera3D);
|
||||||
|
static void _bind_methods();
|
||||||
|
};
|
||||||
36
modules/authority/player_character.cpp
Normal file
36
modules/authority/player_character.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "player_character.h"
|
||||||
|
#include "authority/nav_marker.h"
|
||||||
|
|
||||||
|
void PlayerCharacter::_bind_methods() {}
|
||||||
|
|
||||||
|
void PlayerCharacter::_notification(int what) {
|
||||||
|
if (Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (what) {
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_ENTER_TREE:
|
||||||
|
instance = this;
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_READY:
|
||||||
|
for (Variant var : find_children("*", "NavMarker")) {
|
||||||
|
if (NavMarker * marker{ cast_to<NavMarker>(var) }) {
|
||||||
|
this->party_follow_markers.push_back(marker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ERR_FAIL_COND_EDMSG(this->party_follow_markers.size() < 4, "PlayerCharacter should have at least 4 follow NavMarkers for party members");
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_EXIT_TREE:
|
||||||
|
if (instance == this) {
|
||||||
|
instance = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerCharacter *PlayerCharacter::instance{ nullptr };
|
||||||
|
|
||||||
|
PlayerCharacter *PlayerCharacter::get_singleton() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
21
modules/authority/player_character.h
Normal file
21
modules/authority/player_character.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "authority/character.h"
|
||||||
|
#include "authority/macros.h"
|
||||||
|
#include "authority/nav_marker.h"
|
||||||
|
|
||||||
|
class PlayerCharacter : public Character {
|
||||||
|
GDCLASS(PlayerCharacter, Character);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _notification(int what);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<NavMarker *> party_follow_markers{};
|
||||||
|
static PlayerCharacter *instance;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static PlayerCharacter *get_singleton();
|
||||||
|
GET_SET_FNS(Vector<NavMarker *> const &, party_follow_markers);
|
||||||
|
};
|
||||||
|
|
@ -32,7 +32,7 @@ void PlayerMovementState::process(double delta) {
|
||||||
backward = Vector2{ basis.get_column(1).x, basis.get_column(1).z };
|
backward = Vector2{ basis.get_column(1).x, basis.get_column(1).z };
|
||||||
}
|
}
|
||||||
Vector2 const right{ basis.get_column(2).x, basis.get_column(2).z };
|
Vector2 const right{ basis.get_column(2).x, basis.get_column(2).z };
|
||||||
get_character()->set_movement((backward.normalized() * this->movement.x + right.normalized() * this->movement.y));
|
get_character()->set_movement((backward.normalized() * this->movement.x + right.normalized() * this->movement.y) * get_character()->get_data()->get_speed());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMovementState::_notification(int what) {
|
void PlayerMovementState::_notification(int what) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
#include "register_types.h"
|
#include "register_types.h"
|
||||||
|
|
||||||
#include "authority/character.h"
|
#include "authority/character.h"
|
||||||
|
#include "authority/nav_marker.h"
|
||||||
|
#include "authority/party_member_states.h"
|
||||||
|
#include "authority/player_character.h"
|
||||||
#include "authority/player_states.h"
|
#include "authority/player_states.h"
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
|
|
||||||
|
|
@ -11,8 +14,11 @@ void initialize_authority_module(ModuleInitializationLevel p_level) {
|
||||||
ClassDB::register_class<CharacterData>();
|
ClassDB::register_class<CharacterData>();
|
||||||
ClassDB::register_class<Character>();
|
ClassDB::register_class<Character>();
|
||||||
ClassDB::register_class<CharacterState>();
|
ClassDB::register_class<CharacterState>();
|
||||||
|
ClassDB::register_class<PlayerCharacter>();
|
||||||
ClassDB::register_class<PlayerInputState>();
|
ClassDB::register_class<PlayerInputState>();
|
||||||
ClassDB::register_class<PlayerMovementState>();
|
ClassDB::register_class<PlayerMovementState>();
|
||||||
|
ClassDB::register_class<NavMarker>();
|
||||||
|
ClassDB::register_class<PartyMemberFollow>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninitialize_authority_module(ModuleInitializationLevel p_level) {
|
void uninitialize_authority_module(ModuleInitializationLevel p_level) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
[sub_resource type="CylinderMesh" id="CylinderMesh_5kd2n"]
|
[sub_resource type="CylinderMesh" id="CylinderMesh_5kd2n"]
|
||||||
|
|
||||||
[node name="PlayerCharacter" type="Character" unique_id=1694717421]
|
[node name="PlayerCharacter" type="PlayerCharacter" unique_id=159035892]
|
||||||
data = ExtResource("1_jy05a")
|
data = ExtResource("1_jy05a")
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=511026275]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=511026275]
|
||||||
|
|
@ -16,10 +16,27 @@ shape = SubResource("CapsuleShape3D_vcg8s")
|
||||||
mesh = SubResource("CylinderMesh_5kd2n")
|
mesh = SubResource("CylinderMesh_5kd2n")
|
||||||
|
|
||||||
[node name="Camera3D" type="Camera3D" parent="." unique_id=932811285]
|
[node name="Camera3D" type="Camera3D" parent="." unique_id=932811285]
|
||||||
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 9.536743e-07, 18.920525, -0.37265897)
|
transform = Transform3D(-1, 5.660465e-08, -6.662324e-08, 0, 0.762081, 0.64748174, 8.742278e-08, 0.64748174, -0.762081, 9.536743e-07, 5.8584056, -4.4809494)
|
||||||
current = true
|
current = true
|
||||||
|
far = 1000.0
|
||||||
|
|
||||||
[node name="PlayerInputState" type="PlayerInputState" parent="." unique_id=1290843255]
|
[node name="PlayerInputState" type="PlayerInputState" parent="." unique_id=1290843255]
|
||||||
start_active = true
|
start_active = true
|
||||||
|
|
||||||
[node name="PlayerMovementState" type="PlayerMovementState" parent="." unique_id=71639209]
|
[node name="PlayerMovementState" type="PlayerMovementState" parent="." unique_id=71639209]
|
||||||
|
|
||||||
|
[node name="NavMarker" type="NavMarker" parent="." unique_id=2076207950]
|
||||||
|
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, 2.0248106, 0, -1.4610382)
|
||||||
|
gizmo_extents = 3.0
|
||||||
|
|
||||||
|
[node name="NavMarker2" type="NavMarker" parent="." unique_id=786944405]
|
||||||
|
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, -0.54701775, 9.536743e-07, -2.7108493)
|
||||||
|
gizmo_extents = 3.0
|
||||||
|
|
||||||
|
[node name="NavMarker4" type="NavMarker" parent="." unique_id=1781147686]
|
||||||
|
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, 0.8027056, 9.536743e-07, -2.7077246)
|
||||||
|
gizmo_extents = 3.0
|
||||||
|
|
||||||
|
[node name="NavMarker3" type="NavMarker" parent="." unique_id=430426412]
|
||||||
|
transform = Transform3D(-1, 0, 8.742278e-08, 0, 1, 0, -8.742278e-08, 0, -1, -2.0046833, 9.536743e-07, -1.4623514)
|
||||||
|
gizmo_extents = 3.0
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ config/icon="res://icon.svg"
|
||||||
|
|
||||||
window/size/viewport_width=1920
|
window/size/viewport_width=1920
|
||||||
window/size/viewport_height=1080
|
window/size/viewport_height=1080
|
||||||
window/size/mode=3
|
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[gd_scene format=3 uid="uid://cv0ub3llm3jew"]
|
[gd_scene format=3 uid="uid://cv0ub3llm3jew"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://dcqd0wo5y5a1g" path="res://objects/player_character.tscn" id="1_kyfjp"]
|
[ext_resource type="PackedScene" uid="uid://dcqd0wo5y5a1g" path="res://objects/player_character.tscn" id="1_kyfjp"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dfbdn64i7vfuc" path="res://objects/party_member.tscn" id="2_amxg5"]
|
||||||
|
|
||||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_kyfjp"]
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_kyfjp"]
|
||||||
sky_horizon_color = Color(0.66224277, 0.6717428, 0.6867428, 1)
|
sky_horizon_color = Color(0.66224277, 0.6717428, 0.6867428, 1)
|
||||||
|
|
@ -15,6 +16,10 @@ sky = SubResource("Sky_amxg5")
|
||||||
tonemap_mode = 2
|
tonemap_mode = 2
|
||||||
glow_enabled = true
|
glow_enabled = true
|
||||||
|
|
||||||
|
[sub_resource type="NavigationMesh" id="NavigationMesh_amxg5"]
|
||||||
|
vertices = PackedVector3Array(-8.5, 0.5, -9, -6.5, 0.5, -9, -6.5, 0.5, -49.5, -49.5, 0.5, -7.5, -8.75, 0.5, -7.25, -49.5, 0.5, -49.5, -4.25, 0.5, -9, -4.25, 0.5, -49.5, -2, 0.5, -8.75, 49.5, 0.5, -6.5, 49.5, 0.5, -49.5, -2, 0.5, -6.5, -7.75, 2.5, -8, -7.75, 2.5, -5.25, -3, 2.5, -5.25, -3, 2.5, -8, -49.5, 0.5, -5.75, -8.75, 0.5, -6, -2, 0.5, -4.5, -3.75, 0.5, -4.25, -3.5, 0.5, 49.5, 49.5, 0.5, 49.5, -8.75, 0.5, -4.5, -7, 0.5, -4.25, -49.5, 0.5, 49.5, -7.25, 0.5, 49.5)
|
||||||
|
polygons = [PackedInt32Array(2, 1, 0), PackedInt32Array(4, 3, 0), PackedInt32Array(0, 3, 5), PackedInt32Array(0, 5, 2), PackedInt32Array(2, 7, 1), PackedInt32Array(1, 7, 6), PackedInt32Array(6, 7, 8), PackedInt32Array(8, 7, 10), PackedInt32Array(8, 10, 9), PackedInt32Array(9, 11, 8), PackedInt32Array(15, 14, 12), PackedInt32Array(12, 14, 13), PackedInt32Array(17, 16, 4), PackedInt32Array(4, 16, 3), PackedInt32Array(18, 11, 9), PackedInt32Array(18, 9, 19), PackedInt32Array(19, 9, 20), PackedInt32Array(20, 9, 21), PackedInt32Array(16, 17, 22), PackedInt32Array(22, 23, 16), PackedInt32Array(16, 23, 25), PackedInt32Array(16, 25, 24), PackedInt32Array(23, 19, 25), PackedInt32Array(25, 19, 20)]
|
||||||
|
|
||||||
[node name="TestWorld" type="Node3D" unique_id=262419127]
|
[node name="TestWorld" type="Node3D" unique_id=262419127]
|
||||||
|
|
||||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1185961481]
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1185961481]
|
||||||
|
|
@ -27,13 +32,19 @@ shadow_enabled = true
|
||||||
[node name="PlayerCharacter" parent="." unique_id=1435471129 instance=ExtResource("1_kyfjp")]
|
[node name="PlayerCharacter" parent="." unique_id=1435471129 instance=ExtResource("1_kyfjp")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||||
|
|
||||||
[node name="CSGCombiner3D" type="CSGCombiner3D" parent="." unique_id=885387983]
|
[node name="PartyMember" parent="." unique_id=2124931928 instance=ExtResource("2_amxg5")]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 1, 5)
|
||||||
|
|
||||||
|
[node name="NavigationRegion3D" type="NavigationRegion3D" parent="." unique_id=357996274]
|
||||||
|
navigation_mesh = SubResource("NavigationMesh_amxg5")
|
||||||
|
|
||||||
|
[node name="CSGCombiner3D" type="CSGCombiner3D" parent="NavigationRegion3D" unique_id=885387983]
|
||||||
use_collision = true
|
use_collision = true
|
||||||
|
|
||||||
[node name="CSGBox3D" type="CSGBox3D" parent="CSGCombiner3D" unique_id=1853081325]
|
[node name="CSGBox3D" type="CSGBox3D" parent="NavigationRegion3D/CSGCombiner3D" unique_id=1853081325]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0)
|
||||||
size = Vector3(100, 1, 100)
|
size = Vector3(100, 1, 100)
|
||||||
|
|
||||||
[node name="CSGBox3D2" type="CSGBox3D" parent="CSGCombiner3D" unique_id=40055740]
|
[node name="CSGBox3D2" type="CSGBox3D" parent="NavigationRegion3D/CSGCombiner3D" unique_id=40055740]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.293318, 1.1054688, -6.6544046)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.293318, 1.1054688, -6.6544046)
|
||||||
size = Vector3(5.5302734, 2.2109375, 3.6298828)
|
size = Vector3(5.5302734, 2.2109375, 3.6298828)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue