This commit is contained in:
Oscar 2024-10-29 18:52:47 +03:00
commit 9390a56f64
64 changed files with 23579 additions and 0 deletions

100
.editorconfig Normal file
View File

@ -0,0 +1,100 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
# C# files
[*.{cs,razor}]
indent_style = tab
indent_size = 4
tab_size = 4
# New line preferences
end_of_line = crlf
insert_final_newline = true
#### C# Coding Conventions ####
# Expression-bodied members
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_pattern_matching = true:silent
csharp_style_prefer_switch_expression = true:suggestion
# Null-checking preferences
csharp_style_conditional_delegate_call = true:suggestion
# Code-block preferences
csharp_prefer_braces = true:silent
# Expression-level preferences
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:silent
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = no_change
csharp_indent_switch_labels = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = true
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = true
csharp_space_between_parentheses = control_flow_statements
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# This file describes files and paths that should not be tracked by Git version control
# https://git-scm.com/docs/gitignore
# Auto-generated code editor files
.vs/*
.vscode/*
*.csproj
obj
bin
Properties/*
code/obj/*
code/Properties/*
# Auto-generated asset related files
.sbox/*
*.generated.*
*.*_c
!*.shader_c
*.los
*.vpk
*launchSettings.json
*.sln
*idea
# Exported / standalone games
Exports/

BIN
Assets/maps/nunu.vmap Normal file

Binary file not shown.

View File

@ -0,0 +1,20 @@
{
"publish": {
"Enabled": false,
"ProjectConfig": {
"Title": "nunu",
"Type": "map",
"Org": "local",
"Ident": "nunu",
"Schema": 0,
"IncludeSourceFiles": false,
"Resources": null,
"PackageReferences": [],
"EditorReferences": [],
"IsWhitelistDisabled": false,
"Metadata": {
"SingleAssetSource": "maps/nunu.vmap"
}
}
}
}

BIN
Assets/maps/test.vmap Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -0,0 +1,977 @@
{
"RootObject": {
"__guid": "9ab6bf36-8cdf-4834-bd2a-238fc0cbf804",
"Flags": 0,
"Name": "player",
"Enabled": true,
"Components": [
{
"__type": "ShrimpleCharacterController.ShrimpleCharacterController",
"__guid": "aae5fa89-8749-4ca6-9196-fb35c13baa5c",
"AirAcceleration": 300,
"AirDeceleration": 0,
"Gravity": -850,
"GravityEnabled": true,
"GripFactorReduction": 1,
"GroundAcceleration": 1000,
"GroundDeceleration": 1500,
"GroundStickDistance": 12,
"GroundStickEnabled": true,
"IgnoreGroundSurface": false,
"IgnoreTags": "",
"IgnoreZ": true,
"IgnoreZWhenZero": true,
"ManuallyUpdate": true,
"MaxBounces": 5,
"MaxGroundAngle": 60,
"MaxUnstuckTries": 20,
"PseudoStepsEnabled": true,
"PushEnabled": false,
"PushTagsWeight": {
"player": 1
},
"ScaleAgainstWalls": true,
"StepDepth": 2,
"StepHeight": 12,
"StepsEnabled": true,
"StepTolerance": 1,
"TraceHeight": 72,
"TraceWidth": 16,
"UnstuckEnabled": true,
"UseSceneGravity": true,
"WallTolerance": 1
},
{
"__type": "Kal",
"__guid": "8467b849-9449-492b-b862-76c3c37aee1e",
"CamOffsetX": 200,
"CamOffsetZ": 61,
"DuckSpeed": 50,
"JumpStrength": 350,
"RunSpeed": 300,
"WalkSpeed": 100
},
{
"__type": "Sandbox.Citizen.CitizenAnimationHelper",
"__guid": "640af9e4-02ed-4391-95ea-e45fba51fa42",
"BodyWeight": 1,
"EyesWeight": 1,
"HeadWeight": 1,
"LookAtEnabled": false,
"Target": {
"_type": "component",
"component_id": "4fd8c36d-180b-41af-8439-6b975ca1c7b3",
"go": "b99ceffc-a173-4a6e-a239-6d3c1612c09f",
"component_type": "SkinnedModelRenderer"
}
}
],
"Children": [
{
"__guid": "b99ceffc-a173-4a6e-a239-6d3c1612c09f",
"Flags": 0,
"Name": "Body",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.SkinnedModelRenderer",
"__guid": "4fd8c36d-180b-41af-8439-6b975ca1c7b3",
"BodyGroups": 341,
"CreateBoneObjects": false,
"Model": "models/citizen/citizen.vmdl",
"Morphs": {},
"Parameters": {
"bools": {},
"ints": {},
"floats": {},
"vectors": {},
"rotations": {}
},
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Tint": "1,1,1,1",
"UseAnimGraph": true
}
],
"Children": [
{
"__guid": "55f02b37-0d7a-485b-9ff9-577329327b72",
"Flags": 0,
"Name": "pelvis",
"Position": "1.09978,0.02634115,30.81247",
"Rotation": "-0.4635624,-0.5211884,-0.5340351,0.4777857",
"Enabled": true,
"Children": [
{
"__guid": "e6791e79-6d2f-4889-938a-469e36e7a394",
"Flags": 0,
"Name": "spine_0",
"Position": "3.921841,-0.002455711,-0.000120163",
"Rotation": "-0.0005211234,0.004492462,-0.02736789,-0.9996151",
"Enabled": true,
"Children": [
{
"__guid": "62632f4c-5251-47ee-99e9-5eca787ebd13",
"Flags": 0,
"Name": "spine_1",
"Position": "5.610458,0.000005722046,0.00003051758",
"Rotation": "-0.0001792312,0.007572293,-0.04617235,-0.9989036",
"Enabled": true,
"Children": [
{
"__guid": "9efd1d11-91e3-43b0-8203-122dddd4da0c",
"Flags": 0,
"Name": "spine_2",
"Position": "5.610497,0.00001525879,-0.000007629395",
"Rotation": "-0.0003193617,0.001911119,-0.0103026,-0.9999417",
"Enabled": true,
"Children": [
{
"__guid": "7b3a4b1c-3851-444c-9b10-c59019d02a34",
"Flags": 0,
"Name": "neck_0",
"Position": "5.820332,-0.09347343,-0.003276825",
"Rotation": "0.00003476441,-0.0002155006,0.009900302,-0.9999442",
"Enabled": true,
"Children": [
{
"__guid": "a660f880-88bb-4972-bb01-5a6a2e2d2a84",
"Flags": 0,
"Name": "head",
"Position": "4.511508,-0.0006238669,-0.0008400269",
"Rotation": "-0.000007912517,-0.0000001043081,0.01384526,-0.9998921",
"Enabled": true,
"Children": [
{
"__guid": "ae84828d-d4dc-461b-bbf5-55906713444d",
"Flags": 0,
"Name": "ear_R",
"Position": "5.622315,-0.4147104,-5.930751",
"Rotation": "0.04622595,-0.6934852,0.1379034,-0.7056088",
"Enabled": true
},
{
"__guid": "9f92ced9-922e-41be-ad20-28a016d36589",
"Flags": 0,
"Name": "ear_L",
"Position": "5.62321,-0.4153741,5.927209",
"Rotation": "0.705609,-0.1379605,0.6934716,-0.04625562",
"Enabled": true
},
{
"__guid": "46ddc438-4d04-414e-8c83-da033150c6c5",
"Flags": 0,
"Name": "face_lid_lower_R",
"Position": "6.909532,5.141103,-3.235655",
"Rotation": "-0.1292284,0.9817931,-0.1379476,-0.01812655",
"Enabled": true
},
{
"__guid": "34031d1b-74e3-4053-b701-3e66ec71138b",
"Flags": 0,
"Name": "face_lid_lower_L",
"Position": "6.90997,5.140628,3.233467",
"Rotation": "-0.1292284,0.9817871,0.1379907,0.01812656",
"Enabled": true
},
{
"__guid": "58f01ec1-49fe-4a7b-82ba-5eed960160b6",
"Flags": 0,
"Name": "face_lid_upper_L",
"Position": "6.909989,5.140629,3.233452",
"Rotation": "0.9817871,0.1292284,0.01812819,-0.1379904",
"Enabled": true
},
{
"__guid": "0bf32bb9-e057-419e-a942-c23ea0582433",
"Flags": 0,
"Name": "face_lid_upper_R",
"Position": "6.909554,5.141101,-3.235678",
"Rotation": "0.9817932,0.1292284,-0.01812825,0.1379473",
"Enabled": true
},
{
"__guid": "18358843-3c89-48fd-8be0-5fa0b7955c1f",
"Flags": 0,
"Name": "eye_L",
"Position": "6.911271,5.140766,3.23198",
"Rotation": "0.7092671,0.7048279,0.004742622,-0.004704632",
"Enabled": true
},
{
"__guid": "0ca9dfc6-8ca1-41f9-9d24-f753227f780d",
"Flags": 0,
"Name": "eye_R",
"Position": "6.910652,5.141091,-3.237001",
"Rotation": "0.7092671,0.7048283,0.004742473,-0.004704908",
"Enabled": true
}
]
}
]
},
{
"__guid": "dd94729b-774e-416d-b6c9-d70e663a7549",
"Flags": 0,
"Name": "clavicle_L",
"Position": "4.038403,0.2752094,1.103661",
"Rotation": "-0.08429766,0.6549308,0.08405611,-0.7462444",
"Enabled": true,
"Children": [
{
"__guid": "d26a150a-98eb-418d-966c-53a3e640bfa9",
"Flags": 0,
"Name": "arm_upper_L",
"Position": "6.218311,0.00006532669,-0.001342773",
"Rotation": "-0.06809062,0.6623875,-0.01330963,-0.7459265",
"Enabled": true,
"Children": [
{
"__guid": "7e697fb9-910c-4642-ac8d-4607ac28caed",
"Flags": 0,
"Name": "arm_upper_L_twist1",
"Position": "5.020269,-0.0002432466,-0.002967119",
"Rotation": "0.009102732,-0.00000002980232,0.00000004470348,-0.9999471",
"Enabled": true
},
{
"__guid": "6efdeca4-2f83-42fe-8f96-b2712ec06baf",
"Flags": 0,
"Name": "arm_lower_L",
"Position": "10.04386,0.0002688169,-0.001078844",
"Rotation": "0.0000002831221,-0.0000001192093,-0.1624508,-0.9866987",
"Enabled": true,
"Children": [
{
"__guid": "ba1a0dca-a8c0-4181-ab02-44b9e7fb259b",
"Flags": 0,
"Name": "arm_lower_L_twist0",
"Position": "-0.001255035,-0.0001220703,-0.00227356",
"Rotation": "-0.0000001341105,-0.0000003427267,0.00000001490116,-0.9999745",
"Enabled": true
},
{
"__guid": "79070cab-d818-4c61-ad7d-daf4e8177a65",
"Flags": 0,
"Name": "hand_L",
"Position": "7.705186,0.0006004572,-0.001422405",
"Rotation": "0.02671701,-0.04907528,0.04178061,-0.9975375",
"Enabled": true,
"Children": [
{
"__guid": "a1b8756b-e6e3-4cac-a998-748f1c9ff1f5",
"Flags": 0,
"Name": "hold_L",
"Position": "5.358815,0.6225458,3.392119",
"Rotation": "-0.695914,-0.1704008,-0.3928553,0.5764221",
"Enabled": true
},
{
"__guid": "7fd1f7c4-d1c3-436e-b8d5-a8fe9c55de6d",
"Flags": 0,
"Name": "hand_R_to_L_ikrule",
"Position": "-7.81682,-3.155989,21.13516",
"Rotation": "-0.140897,0.3437678,-0.003125086,-0.928382",
"Enabled": true
},
{
"__guid": "95097fea-f7a1-40cb-acc9-7f56044b1243",
"Flags": 0,
"Name": "finger_thumb_0_L",
"Position": "1.126226,1.648307,0.8637016",
"Rotation": "-0.5683933,-0.1216716,-0.4116745,-0.7018403",
"Enabled": true,
"Children": [
{
"__guid": "cc2772c4-9801-4b63-b85b-1549777e767a",
"Flags": 0,
"Name": "finger_thumb_1_L",
"Position": "1.904869,-0.001191139,-0.004262924",
"Rotation": "-0.00000001024455,0.1627173,-0.00000002793968,-0.9866276",
"Enabled": true,
"Children": [
{
"__guid": "ef0b2fb4-a3c3-4ad2-9f39-a7b6983eba24",
"Flags": 0,
"Name": "finger_thumb_2_L",
"Position": "2.133833,-0.001554489,-0.004840851",
"Rotation": "-0.00000001490116,0.08416325,-0.00000004842877,-0.9963972",
"Enabled": true
}
]
}
]
},
{
"__guid": "07b60cdd-5110-4cee-96dd-5106b51c1fd9",
"Flags": 0,
"Name": "finger_index_meta_L",
"Position": "2.073688,1.204044,0.3748571",
"Rotation": "-0.06033978,-0.04579458,-0.1048825,-0.9915605",
"Enabled": true,
"Children": [
{
"__guid": "836eff99-8079-4fc6-a0fa-276e306ae544",
"Flags": 0,
"Name": "finger_index_0_L",
"Position": "3.066636,0.0002753139,-0.003266573",
"Rotation": "0.003366634,0.2652252,0.06858285,-0.9616922",
"Enabled": true,
"Children": [
{
"__guid": "c0b06cd5-7ca6-4d93-831a-4a6841bca328",
"Flags": 0,
"Name": "finger_index_1_L",
"Position": "2.280267,0.0002042651,-0.002904043",
"Rotation": "0,0.2334992,-0.00000008940697,-0.972301",
"Enabled": true,
"Children": [
{
"__guid": "250e6957-c1d3-4c72-aee1-c337f79511b0",
"Flags": 0,
"Name": "finger_index_2_L",
"Position": "1.590233,0.0002466887,-0.002176881",
"Rotation": "-0.00000005960464,0.0137254,-0.0000003874302,-0.9998416",
"Enabled": true
}
]
}
]
}
]
},
{
"__guid": "9186496c-cad2-4b94-b5d0-47f2ee6a92d8",
"Flags": 0,
"Name": "finger_middle_meta_L",
"Position": "2.099168,-0.1590744,0.2834409",
"Rotation": "-0.008934826,-0.03483182,0.01933663,-0.9991316",
"Enabled": true,
"Children": [
{
"__guid": "50923b14-9231-4087-8d73-a340a8a61028",
"Flags": 0,
"Name": "finger_middle_0_L",
"Position": "2.997435,-0.00002804399,-0.003062844",
"Rotation": "-0.0008631647,0.2334588,-0.001294941,-0.9723202",
"Enabled": true,
"Children": [
{
"__guid": "731dc303-c26e-4eb5-a263-13238cfd353d",
"Flags": 0,
"Name": "finger_middle_1_L",
"Position": "2.557826,0.0001758784,-0.002626687",
"Rotation": "-0.00000008940697,0.2322481,-0.0000002086163,-0.9726022",
"Enabled": true,
"Children": [
{
"__guid": "c5954938-4384-4036-8b7e-f9e163f89603",
"Flags": 0,
"Name": "finger_middle_2_L",
"Position": "1.67947,0.0001565814,-0.001923561",
"Rotation": "-0.0000001341105,0.04821065,-0.0000002682209,-0.9987773",
"Enabled": true
}
]
}
]
}
]
},
{
"__guid": "7ae4b8db-9914-4634-9b2d-96c8ee88536e",
"Flags": 0,
"Name": "finger_ring_meta_L",
"Position": "2.10349,-1.444458,0.2211144",
"Rotation": "0.06374946,0.02917722,0.13065,-0.9889115",
"Enabled": true,
"Children": [
{
"__guid": "6837225a-451f-40f8-8594-b5c63104c45a",
"Flags": 0,
"Name": "finger_ring_0_L",
"Position": "2.822251,-0.0002965927,-0.002760768",
"Rotation": "-0.004488692,0.1855496,-0.05619583,-0.9809707",
"Enabled": true,
"Children": [
{
"__guid": "15bb7037-51de-48d4-b0e9-711193db9d36",
"Flags": 0,
"Name": "finger_ring_1_L",
"Position": "2.194641,-0.00004752725,-0.002517208",
"Rotation": "0.00004316866,0.2565899,0.00004312396,-0.9664629",
"Enabled": true,
"Children": [
{
"__guid": "45867c49-3f20-4c44-87b8-7616f0e28ae8",
"Flags": 0,
"Name": "finger_ring_2_L",
"Position": "1.532103,-0.00003477372,-0.001665652",
"Rotation": "0.0000001788139,-0.05036834,0.0000002384186,0.9986643",
"Enabled": true
}
]
}
]
}
]
}
]
},
{
"__guid": "ce073101-82d3-4a55-858f-df5608f6f8a1",
"Flags": 0,
"Name": "arm_lower_L_twist1",
"Position": "3.850731,0.0001845956,-0.003923535",
"Rotation": "0.01740356,-0.00000001490116,0.00000004470348,-0.9998308",
"Enabled": true
},
{
"__guid": "855af04e-f003-477d-abd8-8e4b9c7b7222",
"Flags": 0,
"Name": "arm_elbow_helper_L",
"Position": "-0.001174927,-0.003246307,-0.002754211",
"Rotation": "0.002399921,0.00216841,0.7619089,-0.6476718",
"Enabled": true
}
]
},
{
"__guid": "254f75ef-591b-48ab-977b-8f05045341c5",
"Flags": 0,
"Name": "arm_upper_L_twist0",
"Position": "-0.002178192,-0.0006027222,-0.003330231",
"Rotation": "0.05913498,0.00000001490116,0,-0.9982385",
"Enabled": true
}
]
}
]
},
{
"__guid": "c3c4078b-1077-4888-bc65-2aeda8abd4a1",
"Flags": 0,
"Name": "clavicle_R",
"Position": "4.037277,0.2748718,-1.108452",
"Rotation": "0.08442839,-0.655288,0.08409488,-0.7459114",
"Enabled": true,
"Children": [
{
"__guid": "15c9abaf-ac95-4941-81a9-cd94d872e53e",
"Flags": 0,
"Name": "arm_upper_R",
"Position": "6.218316,0.0003953613,-0.00002598763",
"Rotation": "0.06907114,-0.6644883,-0.008399844,-0.744036",
"Enabled": true,
"Children": [
{
"__guid": "9c96d6fd-271a-4a7b-a036-6db96dd70497",
"Flags": 0,
"Name": "arm_lower_R",
"Position": "10.04377,0.0008434057,-0.0004107952",
"Rotation": "0.0000002086163,-0.00000002980232,-0.1624506,-0.9866967",
"Enabled": true,
"Children": [
{
"__guid": "b6383140-1e6d-4b46-a1b1-5ed35a1fadd5",
"Flags": 0,
"Name": "arm_lower_R_twist0",
"Position": "-0.001403809,0.0006489754,-0.0008583069",
"Rotation": "0,0.0000001490116,-0.00000005960464,-0.9999706",
"Enabled": true,
"Children": [
{
"__guid": "cfb6423d-393d-449a-bd98-470519e4bd81",
"Flags": 0,
"Name": "arm_elbow_helper_R",
"Position": "-0.001998901,-0.002149105,-0.0009536743",
"Rotation": "0.001526296,0.001149135,0.7618573,-0.647737",
"Enabled": true
}
]
},
{
"__guid": "a860ea26-f03d-48f9-9039-daf136730a1a",
"Flags": 0,
"Name": "hand_R",
"Position": "7.70503,0.001723886,-0.0003260374",
"Rotation": "-0.02671666,0.04907504,0.04178038,-0.9975337",
"Enabled": true,
"Children": [
{
"__guid": "98a9377b-d445-40a7-ae54-25fca52d42c1",
"Flags": 0,
"Name": "hold_R",
"Position": "5.359564,0.6235515,-3.394599",
"Rotation": "0.5764175,-0.3928525,-0.1704,-0.6959082",
"Enabled": true
},
{
"__guid": "6de045f3-a8e5-491b-94ab-f61b6b1aa4ed",
"Flags": 0,
"Name": "hand_L_to_R_ikrule",
"Position": "-7.899995,-3.201715,-21.11883",
"Rotation": "0.1409045,-0.3452918,0.00001519918,-0.9278128",
"Enabled": true
},
{
"__guid": "ccb0ff52-c63f-43c2-9907-7318b9c5166f",
"Flags": 0,
"Name": "finger_thumb_0_R",
"Position": "1.126014,1.649442,-0.8676212",
"Rotation": "-0.5683893,-0.1216713,0.411671,0.7018345",
"Enabled": true,
"Children": [
{
"__guid": "8505adbd-ae44-4f6c-9898-dbeecee80322",
"Flags": 0,
"Name": "finger_thumb_1_R",
"Position": "1.904552,0.000449568,0.0002350211",
"Rotation": "0.00000001303852,0.1627161,-0.00000008195639,0.9866157",
"Enabled": true,
"Children": [
{
"__guid": "48a98f90-49f0-44a5-b01f-1bddad0d1132",
"Flags": 0,
"Name": "finger_thumb_2_R",
"Position": "2.133166,0.0006179959,0.0002120137",
"Rotation": "0.00000001490116,0.08416235,-0.00000006332994,0.9963783",
"Enabled": true
}
]
}
]
},
{
"__guid": "8e12d685-e2e7-409f-8d07-7162f53e18d6",
"Flags": 0,
"Name": "finger_index_meta_R",
"Position": "2.073404,1.205412,-0.3782896",
"Rotation": "0.06033978,0.04579416,-0.1048823,-0.9915539",
"Enabled": true,
"Children": [
{
"__guid": "8bfd5924-6872-43f9-a225-7002c3c60d6f",
"Flags": 0,
"Name": "finger_index_0_R",
"Position": "3.066302,0.002848506,-0.00003266335",
"Rotation": "-0.003366441,-0.2651789,0.06858253,-0.9616932",
"Enabled": true,
"Children": [
{
"__guid": "5be460fd-9370-4863-b5de-82ff3070ae60",
"Flags": 0,
"Name": "finger_index_1_R",
"Position": "2.279522,0.002900422,-0.001230642",
"Rotation": "-0.0000001490116,-0.2334951,0.0000001788139,-0.9722833",
"Enabled": true,
"Children": [
{
"__guid": "215cd42e-5881-4300-8d82-74b3e573bcbb",
"Flags": 0,
"Name": "finger_index_2_R",
"Position": "1.589059,0.003142416,-0.003608108",
"Rotation": "-0.00000007450581,-0.01372504,0.0000004172325,-0.9998136",
"Enabled": true
}
]
}
]
}
]
},
{
"__guid": "590202fa-d1f2-4d0a-9c4e-63cad36df0ec",
"Flags": 0,
"Name": "finger_middle_meta_R",
"Position": "2.099049,-0.1576577,-0.2863335",
"Rotation": "0.008934096,0.03483143,0.01933622,-0.9991246",
"Enabled": true,
"Children": [
{
"__guid": "5b7b506d-b804-48e3-8390-a37e4aee254d",
"Flags": 0,
"Name": "finger_middle_0_R",
"Position": "2.996975,0.002461806,-0.0001957417",
"Rotation": "0.0008631945,-0.2334556,-0.001294434,-0.9723077",
"Enabled": true,
"Children": [
{
"__guid": "3a2205b5-6ea2-414c-a342-5e11746a7f92",
"Flags": 0,
"Name": "finger_middle_1_R",
"Position": "2.556989,0.002898887,-0.001322389",
"Rotation": "-0.00000002980232,-0.2322431,0.0000002384186,-0.9725818",
"Enabled": true,
"Children": [
{
"__guid": "a1465f74-c03d-4c07-9562-5fb1e9f5266c",
"Flags": 0,
"Name": "finger_middle_2_R",
"Position": "1.6782,0.002957284,-0.003669441",
"Rotation": "-0.0000001639128,-0.04820885,0.000000320375,-0.9987424",
"Enabled": true
}
]
}
]
}
]
},
{
"__guid": "1fc09b08-cbeb-438b-8b80-8b1e5d07c5d5",
"Flags": 0,
"Name": "finger_ring_meta_R",
"Position": "2.103528,-1.44299,-0.2234823",
"Rotation": "-0.06374952,-0.02917719,0.1306494,-0.9889046",
"Enabled": true,
"Children": [
{
"__guid": "629acca2-ec4d-49b2-9826-1d36149c4afc",
"Flags": 0,
"Name": "finger_ring_0_R",
"Position": "2.821856,0.001830548,-0.0005825162",
"Rotation": "0.004488915,-0.1855044,-0.05619501,-0.9809677",
"Enabled": true,
"Children": [
{
"__guid": "64c370c9-18ee-4737-a78d-4b765073f922",
"Flags": 0,
"Name": "finger_ring_1_R",
"Position": "2.193966,0.002415007,-0.001737997",
"Rotation": "-0.00004330277,-0.2565853,0.00004337728,-0.9664457",
"Enabled": true,
"Children": [
{
"__guid": "0662b27e-6b7f-42b2-9ad9-070074c10bf2",
"Flags": 0,
"Name": "finger_ring_2_R",
"Position": "1.531064,0.002551214,-0.004439533",
"Rotation": "-0.0000001788139,-0.05036671,0.0000002086163,-0.9986366",
"Enabled": true
}
]
}
]
}
]
}
]
},
{
"__guid": "f5cb25ae-c6a0-4e26-becd-9b5a5915faac",
"Flags": 0,
"Name": "arm_lower_R_twist1",
"Position": "3.850192,0.001937687,-0.001579106",
"Rotation": "-0.01740326,0.00000005960464,0,-0.9998282",
"Enabled": true
}
]
},
{
"__guid": "05ad9f39-b8f6-4dce-af85-d6451bb4886f",
"Flags": 0,
"Name": "arm_upper_R_twist1",
"Position": "5.020006,0.0005286336,-0.001421452",
"Rotation": "-0.009256572,0.00000002980232,-0.00000002980232,-0.9999448",
"Enabled": true
},
{
"__guid": "859eff5e-e24e-4094-adc6-193925b607ef",
"Flags": 0,
"Name": "arm_upper_R_twist0",
"Position": "-0.002349854,0.00006580353,-0.001583099",
"Rotation": "-0.06013197,-0.00000002980232,-0.00000002980232,-0.9981781",
"Enabled": true
}
]
}
]
},
{
"__guid": "b3a3a804-a9dd-4e63-b317-6dc98ef9d8a4",
"Flags": 0,
"Name": "neck_clothing",
"Position": "5.820335,-0.09347534,-0.003288269",
"Rotation": "0.0000089854,-0.0002160072,0.01479772,-0.9998878",
"Enabled": true
}
]
}
]
}
]
},
{
"__guid": "c7082eb0-7445-455f-bea9-8c19435161a2",
"Flags": 0,
"Name": "leg_upper_R",
"Position": "-0.2881527,-0.4264507,-4.427382",
"Rotation": "0.02125055,0.9980782,-0.05431545,0.02094065",
"Enabled": true,
"Children": [
{
"__guid": "b32f3291-da30-407d-be75-11bb1f67ae52",
"Flags": 0,
"Name": "leg_lower_R",
"Position": "14.47042,-0.00000333786,0.000003814697",
"Rotation": "0.004711121,-0.00006237626,0.178974,-0.9838427",
"Enabled": true,
"Children": [
{
"__guid": "482b21bc-f0ce-409d-823e-b8d6d2269469",
"Flags": 0,
"Name": "ankle_R",
"Position": "12.51555,-0.000001907349,0.000001907349",
"Rotation": "-0.03533651,0.009895742,-0.4673119,-0.8833309",
"Enabled": true,
"Children": [
{
"__guid": "96edbe5f-7adf-4361-a639-6c8fe09bc4ea",
"Flags": 0,
"Name": "ball_R",
"Position": "4.429122,-0.0000140667,0.000002384186",
"Rotation": "0.0000002272427,-0.000000461936,-0.3905396,-0.9205871",
"Enabled": true
}
]
},
{
"__guid": "523f8614-bc95-4442-abb0-e1ae05fb1654",
"Flags": 0,
"Name": "leg_lower_R_twist0",
"Rotation": "0.00000005960464,0.0000001192093,-0.00000008940697,-1",
"Enabled": true
},
{
"__guid": "1cb339a4-fa36-4cad-bd3d-542c1fa102f1",
"Flags": 0,
"Name": "leg_lower_R_twist1",
"Position": "6.25779,-0.00001907349,-0.000004768372",
"Rotation": "-0.02398723,0,0.00000001490116,-0.9997125",
"Enabled": true
},
{
"__guid": "4d69aeee-db99-4768-b4bb-1cf7d03259c2",
"Flags": 0,
"Name": "leg_knee_helper_R",
"Position": "-0.007190704,0.05285455,0.0002584457",
"Rotation": "-0.001560916,0.001812547,-0.7461287,-0.6657979",
"Enabled": true
}
]
},
{
"__guid": "bbe8f2e8-e480-4ab3-9dc0-20f8fa200059",
"Flags": 0,
"Name": "leg_upper_R_twist1",
"Position": "7.235819,-0.00001811981,-0.000003814697",
"Rotation": "0.005437598,0,0,-0.9999852",
"Enabled": true
},
{
"__guid": "37ec1971-f2bf-4e61-bcbb-5e385e417200",
"Flags": 0,
"Name": "leg_upper_R_twist0",
"Rotation": "0.03533095,-0.00000002980232,-0.00000002980232,-0.9993757",
"Enabled": true
},
{
"__guid": "d46108e1-4cc8-4a5d-a4fc-11efb1ce3820",
"Flags": 0,
"Name": "leg_glute_helper_R",
"Rotation": "-0.0000002980232,-0.0000003241003,0.7070966,-0.7071172",
"Enabled": true
}
]
},
{
"__guid": "afc7ee64-84d0-478b-b845-dbffc38db7dc",
"Flags": 0,
"Name": "leg_upper_L",
"Position": "-0.2881393,-0.4264393,4.427385",
"Rotation": "-0.007433116,0.9984711,0.05426106,0.007487625",
"Enabled": true,
"Children": [
{
"__guid": "69d94113-1d92-4570-a461-9b8f626ac512",
"Flags": 0,
"Name": "leg_lower_L",
"Position": "14.47038,0.000004768372,0.000008583069",
"Rotation": "0.004010305,-0.00003439188,0.1198097,-0.9927889",
"Enabled": true,
"Children": [
{
"__guid": "66e60c1d-f2bd-4378-b9b6-3fdd3fc5d9fe",
"Flags": 0,
"Name": "ankle_L",
"Position": "12.51555,-0.000001430511,0.000002861023",
"Rotation": "0.02723786,-0.008950412,-0.4382423,-0.8983996",
"Enabled": true,
"Children": [
{
"__guid": "862b07fd-7c61-474d-a24b-03bf3b697f20",
"Flags": 0,
"Name": "ball_L",
"Position": "4.429139,-0.000002622604,-0.000003814697",
"Rotation": "-0.00000008568168,0.0000003129244,0.3907111,0.9205113",
"Enabled": true
}
]
},
{
"__guid": "1b62659b-781f-49ab-a38c-bc4918c2f243",
"Flags": 0,
"Name": "leg_lower_L_twist0",
"Rotation": "-0.00000008940697,-0.0000002980232,-0.00000004470348,-0.9999992",
"Enabled": true
},
{
"__guid": "f215b579-d99b-4a73-a82b-41c25c97acae",
"Flags": 0,
"Name": "leg_lower_L_twist1",
"Position": "6.257804,-0.00002193451,0.000001907349",
"Rotation": "0.01818442,0.00000002980232,0.00000002980232,-0.9998348",
"Enabled": true
},
{
"__guid": "bcb4f9d6-b22f-43f6-8bee-be2026635707",
"Flags": 0,
"Name": "leg_knee_helper_L",
"Position": "-0.00188446,0.03569415,0.0001401901",
"Rotation": "0.001566295,-0.001615524,0.7499412,0.6615008",
"Enabled": true
}
]
},
{
"__guid": "872c631e-66d0-491e-a5d3-18703c10bb82",
"Flags": 0,
"Name": "leg_upper_L_twist1",
"Position": "7.235796,-0.00002574921,0",
"Rotation": "-0.0054297,-0.00000001490116,-0.00000004470348,-0.9999853",
"Enabled": true
},
{
"__guid": "ab710057-1eb5-4c83-a428-d79899eec4df",
"Flags": 0,
"Name": "leg_upper_L_twist0",
"Rotation": "-0.03528263,0,0.00000002980232,-0.9993776",
"Enabled": true
},
{
"__guid": "1319a98f-6a9e-4434-b355-6311d621c89c",
"Flags": 0,
"Name": "leg_glute_helper_L",
"Rotation": "-0.0000002682209,-0.0000002249144,0.7070962,-0.7071172",
"Enabled": true
}
]
}
]
},
{
"__guid": "119ce4a2-be0f-4dea-9d7e-7ca2e5bf2834",
"Flags": 0,
"Name": "root_IK",
"Position": "1.180664,0.000006914139,0.00001496077",
"Enabled": true,
"Children": [
{
"__guid": "5f6e553c-71cf-47d8-a2a8-085fa016a462",
"Flags": 0,
"Name": "hand_R_IK_target",
"Position": "-2.719624,-11.35815,33.26634",
"Rotation": "0.4582616,0.3513036,-0.6075084,0.5454503",
"Enabled": true
},
{
"__guid": "f4dd759e-5fb0-4065-b438-39d2233d982f",
"Flags": 0,
"Name": "hand_L_IK_target",
"Position": "-2.719516,11.35806,33.26635",
"Rotation": "0.5454503,0.6075078,-0.3513034,0.4582625",
"Enabled": true
},
{
"__guid": "5f8c54a4-c53b-4523-a10e-ded075d50d2c",
"Flags": 0,
"Name": "aim_matrix_02a",
"Position": "4.638925,-0.0000008343591,9.8425",
"Enabled": true,
"Children": [
{
"__guid": "f67b6696-c5d8-454c-adf1-ca932644a8c4",
"Flags": 0,
"Name": "aim_matrix_02b",
"Position": "3.937002,-0.0000004822496,-0.0000009536743",
"Enabled": true
}
]
},
{
"__guid": "68eac2de-d762-42ad-aec1-2e6ddac68b31",
"Flags": 0,
"Name": "aim_matrix_01",
"Position": "4.638925,-0.0000008343591,11.811",
"Enabled": true
},
{
"__guid": "0c2813a3-57fd-49c5-8133-fc4ea6b5eb0d",
"Flags": 0,
"Name": "foot_R_IK_target",
"Position": "-0.773421,-4.402194,3.807818",
"Rotation": "0.672557,0.2183617,-0.3318372,0.6243953",
"Enabled": true
},
{
"__guid": "fa33beab-3dce-4e46-84c5-80c8fff6815b",
"Flags": 0,
"Name": "foot_L_IK_target",
"Position": "-0.769591,4.402877,3.80613",
"Rotation": "0.6243098,0.3319235,-0.2184912,0.6725516",
"Enabled": true
}
]
}
]
}
],
"__variables": [],
"__properties": {
"FixedUpdateFrequency": 50,
"MaxFixedUpdates": 5,
"NetworkFrequency": 30,
"NetworkInterpolation": true,
"PhysicsSubSteps": 1,
"ThreadedAnimation": true,
"TimeScale": 1,
"UseFixedUpdate": true,
"Metadata": {},
"NavMesh": {
"Enabled": false,
"IncludeStaticBodies": true,
"IncludeKeyframedBodies": true,
"EditorAutoUpdate": true,
"AgentHeight": 64,
"AgentRadius": 16,
"AgentStepSize": 18,
"AgentMaxSlope": 40,
"ExcludedBodies": "",
"IncludedBodies": ""
}
}
},
"ShowInMenu": false,
"MenuPath": null,
"MenuIcon": null,
"DontBreakAsTemplate": false,
"ResourceVersion": 1,
"__references": [],
"__version": 1
}

386
Assets/scenes/minimal.scene Normal file
View File

@ -0,0 +1,386 @@
{
"__guid": "325a4042-0696-43dd-a79d-dcc314299ba3",
"GameObjects": [
{
"__guid": "2563f4af-75f3-40e1-9370-d548bbfe7a6e",
"Flags": 0,
"Name": "NetworkManager",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.SceneInformation",
"__guid": "76de2a71-7d23-4f8a-a425-e4ceb539cfae",
"Description": "",
"SceneTags": "",
"Title": "minimal"
},
{
"__type": "Sandbox.NetworkHelper",
"__guid": "f98c20e4-aa1c-4737-a771-e8391b397d2a",
"PlayerPrefab": {
"_type": "gameobject",
"prefab": "prefabs/player.prefab"
},
"SpawnPoints": [],
"StartServer": true
}
]
},
{
"__guid": "bfc59c12-1ed2-4f91-8956-a95a315eac3c",
"Flags": 0,
"Name": "Sun",
"Rotation": "-0.0729315,0.4822396,0.1305433,0.8631827",
"Tags": "light_directional,light",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.DirectionalLight",
"__guid": "d3659344-a90d-48fa-927a-095f70fe041f",
"FogMode": "Enabled",
"FogStrength": 1,
"LightColor": "0.94419,0.97767,1,1",
"Shadows": true,
"SkyColor": "0.2532,0.32006,0.35349,1"
}
]
},
{
"__guid": "00344a8c-fa5e-45ae-b12a-10bb781a1dc3",
"Flags": 0,
"Name": "2D Skybox",
"Tags": "skybox",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.SkyBox2D",
"__guid": "de79e9e0-5c37-4c54-ac67-bfcdb1d5483b",
"SkyIndirectLighting": true,
"SkyMaterial": "materials/skybox/skybox_day_01.vmat",
"Tint": "1,1,1,1"
},
{
"__type": "Sandbox.EnvmapProbe",
"__guid": "f3e304db-baab-4c1a-a4ec-8442585c2d62",
"Texture": "textures/cubemaps/default2.vtex",
"Bounds": {
"Mins": "-512,-512,-512",
"Maxs": "512,512,512"
},
"DelayBetweenUpdates": 0.1,
"Feathering": 0.02,
"FrameInterval": 5,
"MaxDistance": 512,
"MultiBounce": false,
"Projection": "Sphere",
"RenderDynamically": false,
"TintColor": "1,1,1,1",
"UpdateStrategy": "OnEnabled",
"ZFar": 4096,
"ZNear": 16
}
]
},
{
"__guid": "6ad70641-3c6c-4402-9c85-9a4969af4764",
"Flags": 0,
"Name": "Plane",
"Scale": "5,5,5",
"Components": [
{
"__type": "Sandbox.ModelRenderer",
"__guid": "0b6a18bf-fdb8-4661-970e-ef635bfa9baa",
"BodyGroups": 18446744073709551615,
"MaterialOverride": "materials/default.vmat",
"Model": "models/dev/plane.vmdl",
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Tint": "0.39546,0.51163,0.27128,1"
},
{
"__type": "Sandbox.BoxCollider",
"__guid": "0715cb55-1733-4f5e-8560-c288b8695631",
"Center": "0,0,-5",
"IsTrigger": false,
"Scale": "100,100,10",
"Static": false,
"SurfaceVelocity": "0,0,0"
}
]
},
{
"__guid": "3c2490ef-54a0-49bb-8f13-490e40aa51d1",
"Flags": 0,
"Name": "Cube",
"Position": "-18.53616,-147.7339,86.60748",
"Rotation": "0.00000001819328,-0.00000000000000008235059,0.3052325,0.952278",
"Scale": "0.5632889,0.5632889,0.5632889",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.ModelRenderer",
"__guid": "b9121ffa-617c-4ccc-a2aa-8acc98727590",
"BodyGroups": 18446744073709551615,
"MaterialOverride": "materials/default.vmat",
"Model": "models/dev/box.vmdl",
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Tint": "1,0,0.93333,1"
},
{
"__type": "Sandbox.BoxCollider",
"__guid": "8bb3ebcf-1ec9-4b20-bf31-4aece0950008",
"Center": "0,0,0",
"IsTrigger": false,
"Scale": "50,50,50",
"Static": false,
"SurfaceVelocity": "0,0,0"
},
{
"__type": "Sandbox.Rigidbody",
"__guid": "4aaa0334-6785-4716-9bae-869559ea6e10",
"AngularDamping": 0,
"Gravity": true,
"LinearDamping": 0,
"Locking": {},
"MassCenterOverride": "0,0,0",
"MassOverride": 0,
"MotionEnabled": true,
"OverrideMassCenter": false,
"RigidbodyFlags": 0,
"StartAsleep": false
}
]
},
{
"__guid": "523e3e8f-a4ec-4ec1-af9a-d86ffc9c17e1",
"Flags": 0,
"Name": "Cube (1)",
"Position": "40.81348,46.97572,14.40159",
"Rotation": "0.00000001819328,-0.00000000000000008235059,0.3052325,0.952278",
"Scale": "0.5632889,0.5632889,0.5632889",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.ModelRenderer",
"__guid": "9e8a546d-a41d-44b5-9906-22cea00e1066",
"BodyGroups": 18446744073709551615,
"MaterialOverride": "materials/default.vmat",
"Model": "models/dev/box.vmdl",
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Tint": "1,0,0.93333,1"
},
{
"__type": "Sandbox.BoxCollider",
"__guid": "adf22580-7a25-4d7f-b1c3-3fb8fabf1612",
"Center": "0,0,0",
"IsTrigger": false,
"Scale": "50,50,50",
"Static": false,
"SurfaceVelocity": "0,0,0"
},
{
"__type": "Sandbox.Rigidbody",
"__guid": "e53bfcb0-7f44-41d0-8d51-263bdc173a57",
"AngularDamping": 0,
"Gravity": true,
"LinearDamping": 0,
"Locking": {},
"MassCenterOverride": "0,0,0",
"MassOverride": 0,
"MotionEnabled": true,
"OverrideMassCenter": false,
"RigidbodyFlags": 0,
"StartAsleep": false
}
]
},
{
"__guid": "5b483a09-bbf2-4949-98c7-a73b789d0ee7",
"Flags": 0,
"Name": "Cube (2)",
"Position": "49.53706,34.08897,128.0143",
"Rotation": "0.00000001819328,-0.00000000000000008235059,0.3052325,0.952278",
"Scale": "0.5632889,0.5632889,0.5632889",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.ModelRenderer",
"__guid": "ac284ab8-cdb7-4ba6-92de-d9be36088b1b",
"BodyGroups": 18446744073709551615,
"MaterialOverride": "materials/default.vmat",
"Model": "models/dev/box.vmdl",
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Tint": "1,0,0.93333,1"
},
{
"__type": "Sandbox.BoxCollider",
"__guid": "ca4eb284-231e-4c84-9bc4-7ba89962f307",
"Center": "0,0,0",
"IsTrigger": false,
"Scale": "50,50,50",
"Static": false,
"SurfaceVelocity": "0,0,0"
},
{
"__type": "Sandbox.Rigidbody",
"__guid": "61ef15dd-3eb2-4f52-8b9a-315f477f79b7",
"AngularDamping": 0,
"Gravity": true,
"LinearDamping": 0,
"Locking": {},
"MassCenterOverride": "0,0,0",
"MassOverride": 0,
"MotionEnabled": true,
"OverrideMassCenter": false,
"RigidbodyFlags": 0,
"StartAsleep": false
}
]
},
{
"__guid": "3ee1c9f4-07be-4e0b-8b23-67bee2d8ec8a",
"Flags": 0,
"Name": "Camera",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.CameraComponent",
"__guid": "cf3cbf96-22b6-4be4-a5d0-672a96c17f9f",
"BackgroundColor": "0.33333,0.46275,0.52157,1",
"ClearFlags": "All",
"FieldOfView": 60,
"IsMainCamera": true,
"Orthographic": false,
"OrthographicHeight": 1204,
"Priority": 1,
"RenderExcludeTags": "",
"RenderTags": "",
"TargetEye": "None",
"Viewport": "0,0,1,1",
"ZFar": 10000,
"ZNear": 10
},
{
"__type": "Sandbox.Bloom",
"__guid": "d73ef723-c888-41d4-802e-f797c79318be",
"BloomColor": {
"color": [
{
"c": "1,1,1,1"
},
{
"t": 1,
"c": "1,1,1,1"
}
],
"alpha": []
},
"BloomCurve": [
{
"y": 0.5
},
{
"x": 1,
"y": 1
}
],
"Mode": "Additive",
"Strength": 0.5,
"Threshold": 0.5,
"ThresholdWidth": 0.5
},
{
"__type": "Sandbox.Tonemapping",
"__guid": "9d76f362-7227-40eb-a189-69353c780c46",
"__version": 1,
"AutoExposureEnabled": true,
"ExposureBias": 2,
"ExposureCompensation": 0,
"ExposureMethod": "RGB",
"MaximumExposure": 2,
"MinimumExposure": 1,
"Mode": "Legacy",
"Rate": 1
},
{
"__type": "Sandbox.Sharpen",
"__guid": "0bffee5e-19f2-41c4-88f9-faefbcce6bf4",
"Scale": 0.2
}
]
},
{
"__guid": "cf125021-fa85-46d4-9ad8-6ea4ac3cc1e9",
"Flags": 0,
"Name": "mmm",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.MapInstance",
"__guid": "6e911feb-4dd7-4be6-9729-e48480e2ed2a",
"__version": 1,
"EnableCollision": true,
"MapName": "maps/nunu.vmap",
"NoOrigin": false,
"OnMapLoaded": null,
"OnMapUnloaded": null,
"UseMapFromLaunch": false
}
],
"Children": []
}
],
"SceneProperties": {
"FixedUpdateFrequency": 50,
"MaxFixedUpdates": 5,
"NetworkFrequency": 60,
"NetworkInterpolation": true,
"PhysicsSubSteps": 1,
"ThreadedAnimation": true,
"TimeScale": 1,
"UseFixedUpdate": true,
"Metadata": {
"Title": "minimal"
},
"NavMesh": {
"Enabled": false,
"IncludeStaticBodies": true,
"IncludeKeyframedBodies": true,
"EditorAutoUpdate": true,
"AgentHeight": 64,
"AgentRadius": 16,
"AgentStepSize": 18,
"AgentMaxSlope": 40,
"ExcludedBodies": "",
"IncludedBodies": ""
}
},
"ResourceVersion": 2,
"Title": "minimal",
"Description": null,
"__references": [],
"__version": 2
}

View File

@ -0,0 +1,22 @@
{
"publish": {
"Enabled": false,
"ProjectConfig": {
"Title": "test",
"Type": "map",
"Org": "local",
"Ident": "test",
"Schema": 0,
"IncludeSourceFiles": false,
"Resources": null,
"PackageReferences": [],
"EditorReferences": [
"matek.dev_checker_light#46462"
],
"IsWhitelistDisabled": false,
"Metadata": {
"SingleAssetSource": "scenes/test.vmap"
}
}
}
}

10
Assets/untitled.motivate Normal file
View File

@ -0,0 +1,10 @@
{
"Portraits": [
"photo_2024-10-16_19-53-34.jpg"
],
"Messages": [
"\u0415\u0431\u0430\u0448, \u0434\u0430 \u043D\u0435 \u0432\u044B\u0435\u0431\u0430\u043D \u0431\u0443\u0434\u0435\u0448\u044C"
],
"__references": [],
"__version": 0
}

View File

@ -0,0 +1,20 @@
{
"publish": {
"Enabled": true,
"ProjectConfig": {
"Title": "untitled",
"Type": "motivate",
"Org": "local",
"Ident": "untitled",
"Schema": 0,
"IncludeSourceFiles": true,
"Resources": null,
"PackageReferences": null,
"EditorReferences": null,
"IsWhitelistDisabled": false,
"Metadata": {
"SingleAssetSource": "untitled.motivate"
}
}
}
}

3
Code/Assembly.cs Normal file
View File

@ -0,0 +1,3 @@
global using Sandbox;
global using System.Collections.Generic;
global using System.Linq;

101
Code/Kal.cs Normal file
View File

@ -0,0 +1,101 @@
using Sandbox.Citizen;
using ShrimpleCharacterController;
public sealed class Kal : Component
{
[RequireComponent]
public ShrimpleCharacterController.ShrimpleCharacterController Controller { get; set; }
[RequireComponent]
public CitizenAnimationHelper AnimationHelper { get; set; }
public SkinnedModelRenderer Renderer { get; set; }
public GameObject Camera { get; set; }
[Property]
[Range(1f, 200f, 1f)]
public float CamOffsetX { get; set; }
[Property]
[Range(1f, 200f, 1f)]
public float CamOffsetZ { get; set; }
[Property]
[Range(50f, 200f, 10f)]
public float WalkSpeed { get; set; } = 100f;
[Property]
[Range(100f, 500f, 20f)]
public float RunSpeed { get; set; } = 300f;
[Property]
[Range(25f, 100f, 5f)]
public float DuckSpeed { get; set; } = 50f;
[Property]
[Range(200f, 500f, 20f)]
public float JumpStrength { get; set; } = 350f;
public Angles EyeAngles { get; set; }
protected override void OnStart()
{
base.OnStart();
if ( !Network.IsOwner ) return;
Renderer = Components.Get<SkinnedModelRenderer>(FindMode.EverythingInSelfAndDescendants);
Camera = new GameObject(true, "Camera");
Camera.SetParent(GameObject);
var cameraComponent = Camera.Components.Create<CameraComponent>();
cameraComponent.ZFar = 32768f;
}
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
if ( !Network.IsOwner ) return;
var wishDirection = Input.AnalogMove.Normal * Rotation.FromYaw(EyeAngles.yaw);
var isDucking = Input.Down("Duck");
var isRunning = Input.Down("Run");
var wishSpeed = isDucking ? DuckSpeed :
isRunning ? RunSpeed : WalkSpeed;
Controller.WishVelocity = wishDirection * wishSpeed;
Controller.Move();
if (Input.Pressed("Jump") && Controller.IsOnGround)
{
Controller.Punch(Vector3.Up * JumpStrength * 10f);
AnimationHelper?.TriggerJump();
}
if (!AnimationHelper.IsValid()) return;
AnimationHelper.WithWishVelocity(Controller.WishVelocity);
AnimationHelper.WithVelocity(Controller.Velocity);
AnimationHelper.DuckLevel = isDucking ? 1f : 0f;
AnimationHelper.IsGrounded = Controller.IsOnGround;
}
protected override void OnUpdate()
{
base.OnUpdate();
Log.Info(Controller.WishVelocity);
if ( !Network.IsOwner ) return;
Log.Info(Controller.WishVelocity);
EyeAngles += Input.AnalogLook;
EyeAngles = EyeAngles.WithPitch(MathX.Clamp(EyeAngles.pitch, -10f, 40f));
Renderer.WorldRotation = Rotation.Slerp(Renderer.WorldRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 5f);
var cameraOffset = Vector3.Up * CamOffsetZ + Vector3.Backward * CamOffsetX;
Camera.WorldRotation = EyeAngles.ToRotation();
Camera.LocalPosition = cameraOffset * Camera.WorldRotation;
}
}

9
Code/MyComponent.cs Normal file
View File

@ -0,0 +1,9 @@
public sealed class MyComponent : Component
{
[Property] public string StringProperty { get; set; }
protected override void OnUpdate()
{
}
}

4
Editor/Assembly.cs Normal file
View File

@ -0,0 +1,4 @@
global using Sandbox;
global using Editor;
global using System.Collections.Generic;
global using System.Linq;

8
Editor/MyEditorMenu.cs Normal file
View File

@ -0,0 +1,8 @@
public static class MyEditorMenu
{
[Menu("Editor", "$title/My Menu Option")]
public static void OpenMyMenu()
{
EditorUtility.DisplayDialog("It worked!", "This is being called from your library's editor code!");
}
}

View File

@ -0,0 +1,4 @@
[
"package.base",
"package.badandbest.youcandoit"
]

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>package.badandbest.youcandoit</name>
</assembly>
<members>
</members>
</doc>

Binary file not shown.

View File

@ -0,0 +1 @@
1.0.73517

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,20 @@
{
"Portraits": [
"portraits/physgun.png",
"portraits/suspicious.png"
],
"Messages": [
"very good.",
"congratulations.",
"keep it up!",
"that\u0027s smart.",
"I like your thinking.",
"that\u0027s a good idea.",
"neat.",
"interesting..",
"very clever."
],
"__references": [],
"IsValid": true,
"__version": 0
}

Binary file not shown.

View File

@ -0,0 +1,27 @@
{
"Portraits": [
"portraits/arms_crossed.png"
],
"Messages": [
"Hmph!",
"Baka!",
"Do better!",
"\u003E:C",
"*pout*",
"Idiot!",
"Stupid head!",
"It\u0027s not like\nI\u0027m proud of you\nor anything!",
"It\u0027s not like\nI care about your\nwork or anything!",
"Finish it already!",
"Geez, stop pushing\nyourself!",
"Could you be any\nmore clueless?",
"It doesn\u0027t work!",
"Finish it faster!",
"Blehh!",
"You suck! (\u25D4_\u25D4)",
"Useless!"
],
"__references": [],
"IsValid": true,
"__version": 0
}

View File

@ -0,0 +1,27 @@
{
"Portraits": [
"portraits/pumped.png",
"portraits/heart.png"
],
"Messages": [
"good work! :3",
"keep at it! c:",
"rawr! so cool!!",
"WOW!",
"need some hewp?",
"um.. w-what are\nyou working on?",
"that\u0027s amazing!\n(\u2217\u2022\u03C9\u2022\u2217)",
"s-sorryy.. am i\ninterrupt?",
"you can do it!!",
"you sure you don\u0027t\nneed a break? (\u00B4\uFF65\u03C9\uFF65\u0060)",
"this is gonna be\nsoo cool!",
"keep working hard\nsenpai!",
"can you teach me?",
"just a little more!",
"i love it!",
"are you oki?"
],
"__references": [],
"IsValid": true,
"__version": 0
}

View File

@ -0,0 +1,3 @@
global using Sandbox;
global using System.Collections.Generic;
global using System.Linq;

View File

@ -0,0 +1,31 @@
using Sandbox;
using System;
namespace Editor;
public static class MotivationManager
{
static RealTimeUntil Cooldown;
static MotivationManager()
{
Game.SetRandomSeed( DateTime.Now.Second );
Cooldown = 5;
}
[EditorEvent.FrameAttribute]
public static void Frame()
{
if ( !Cooldown )
{
return;
}
var notice = new MotivationNotice();
NoticeManager.Remove( notice, 30 );
const int MIN_MINUTES = 15;
const int MAX_MINUTES = 30;
Cooldown = 60 * Game.Random.Next( MIN_MINUTES, MAX_MINUTES );
}
}

View File

@ -0,0 +1,37 @@
using Sandbox;
using System.Linq;
using static Sandbox.ResourceLibrary;
namespace Editor;
public class MotivationNotice : NoticeWidget
{
public string Portrait { get; init; }
public string Message { get; init; }
public string Bubble => FileSystem.Mounted.GetFullPath( "portraits/bubble.png" );
protected override Vector2 SizeHint() => new( 512, 384 );
public MotivationNotice()
{
var personality = Game.Random.FromArray( GetAll<MotivationResource>().ToArray() );
Portrait = personality.GetPortrait();
Message = personality.GetMessage();
}
protected override void OnPaint()
{
Paint.SetPen( Theme.Black );
Paint.SetDefaultFont( 16 );
var rect = LocalRect.Align( 350, TextFlag.LeftBottom );
Paint.Draw( rect, Portrait );
rect = LocalRect.Align( 250, TextFlag.RightTop );
Paint.Draw( rect, Bubble );
rect = rect.Shrink( 0, 0, 0, 55 );
Paint.DrawText( rect, Message );
}
}

View File

@ -0,0 +1,31 @@
using Sandbox;
namespace Editor;
[GameResource( "Motivation", "motivate", "Citizens motivate you every 15-30 minutes.", Icon = "support_agent", Category = "Editor", IconBgColor = "#E4E2E4", IconFgColor = "#93BDDD" )]
public class MotivationResource : GameResource
{
[ImageAssetPath]
public string[] Portraits { get; set; }
public string[] Messages { get; set; }
/// <summary>
/// Selects a random citizen portrait from this type.
/// </summary>
/// <returns>Portrait file path</returns>
public string GetPortrait()
{
var portraitPath = Game.Random.FromArray( Portraits );
return FileSystem.Mounted.GetFullPath( portraitPath );
}
/// <summary>
/// Selects a random motivational response from this type.
/// </summary>
/// <returns>Response with linebreaks</returns>
public string GetMessage()
{
return Game.Random.FromArray( Messages );
}
}

View File

@ -0,0 +1,25 @@
{
"Title": "You Can Do It!",
"Type": "library",
"Org": "badandbest",
"Ident": "youcandoit",
"Schema": 1,
"IncludeSourceFiles": true,
"Resources": null,
"PackageReferences": [],
"EditorReferences": null,
"IsWhitelistDisabled": false,
"Metadata": {
"CsProjName": "You Can Do It",
"Compiler": {
"RootNamespace": "Sandbox",
"DefineConstants": "SANDBOX;ADDON;DEBUG",
"NoWarn": "1701;1702;1591;2255;",
"WarningsAsErrors": "",
"Whitelist": true,
"AssemblyReferences": [],
"IgnoreFolders": [],
"DistinctAssemblyReferences": []
}
}
}

View File

@ -0,0 +1,4 @@
[
"package.base",
"package.fish.scc"
]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,287 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>package.fish.scc</name>
</assembly>
<members>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.ManuallyUpdate">
<summary>
Manually update this by calling Move() or let it always be simulated
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.ScaleAgainstWalls">
<summary>
If pushing against a wall, scale the velocity based on the wall's angle (False is useful for NPCs that get stuck on corners)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.TraceWidth">
<summary>
Width of our trace
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.TraceHeight">
<summary>
Height of our trace
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IgnoreTags">
<summary>
Which tags it should ignore
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.MaxBounces">
<summary>
Max amount of trace calls whenever the simulation doesn't reach its target (Slide and collide bounces)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GroundAcceleration">
<summary>
How fast you accelerate while on the ground (Units per second)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GroundDeceleration">
<summary>
How fast you decelerate while on the ground (Units per second)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.AirAcceleration">
<summary>
How fast you accelerate while in the air (Units per second)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.AirDeceleration">
<summary>
How fast you decelerate while in the air (Units per second)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IgnoreGroundSurface">
<summary>
Do we ignore the friction of the surface you're standing on or not?
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IgnoreZ">
<summary>
Is this MoveHelper meant for horizontal grounded movement? (false = For flying or noclip)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IgnoreZWhenZero">
<summary>
Do we ignore Z when it's near 0 (So that gravity affects you when not moving)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.WallTolerance">
<summary>
Tolerance from a 90° surface before it's considered a wall (Ex. Tolerance 1 = Between 89° and 91° can be a wall, 0.1 = 89.9° to 90.1°)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GripFactorReduction">
<summary>
Player feels like it's gripping walls too much? Try more Grip Factor Reduction!
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GroundStickEnabled">
<summary>
Stick the MoveHelper to the ground (IsOnGround will default to false if disabled)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.MaxGroundAngle">
<summary>
How steep terrain can be for you to stand on without slipping
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GroundStickDistance">
<summary>
How far from the ground the MoveHelper is going to stick (Useful for going down stairs!)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.StepsEnabled">
<summary>
Enable steps climbing (+1 Trace call)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.StepHeight">
<summary>
How high steps can be for you to climb on
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.StepDepth">
<summary>
How deep it checks for steps (Minimum depth)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.StepTolerance">
<summary>
Tolerance from a 90° surface before it's considered a valid step (Ex. Tolerance 1 = Between 89° and 91° can be a step, 0.1 = 89.9° to 90.1°)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.PseudoStepsEnabled">
<summary>
Enable to ability to walk on a surface that's too steep if it's equal or smaller than a step (+1 Trace call when on steep terrain)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.PushEnabled">
<summary>
Instead of colliding with these tags the MoveHelper will be pushed away (Make sure the tags are in IgnoreTags as well!)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.PushTagsWeight">
<summary>
Which tags will push this MoveHelper away and with how much force (Make sure they are also included in IgnoreTags!) (+1 Trace call)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GravityEnabled">
<summary>
Apply gravity to this MoveHelper when not on the ground
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.UseSceneGravity">
<summary>
Use the scene's gravity or our own
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.Gravity">
<summary>
Units per second squared (Default is -850f)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.UnstuckEnabled">
<summary>
Check if the MoveHelper is stuck and try to get it to unstuck (+Trace calls if stuck)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.MaxUnstuckTries">
<summary>
How many trace calls it will attempt to get the MoveHelper unstuck
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.WishVelocity">
<summary>
The simulated target velocity for our MoveHelper (Units per second, we apply Time.Delta inside)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.Velocity">
<summary>
The resulting velocity after the simulation is done (Units per second)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IsOnGround">
<summary>
Is the MoveHelper currently touching the ground
</summary>
</member>
<!-- Badly formed XML comment ignored for member "P:ShrimpleCharacterController.ShrimpleCharacterController.GroundNormal" -->
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GroundAngle">
<summary>
The current ground angle you're standing on (Always 0f if IsOnGround false)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GroundSurface">
<summary>
The current surface you're standing on
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.GroundObject">
<summary>
The gameobject you're currently standing on
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IsPushingAgainstWall">
<summary>
Is the MoveHelper currently pushing against a wall
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.WallNormal">
<summary>
The current wall normal you're pushing against (Always Vector3.Zero if IsPushingAgainstWall false)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.WallObject">
<summary>
The gameobject you're currently pushing on
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IsSlipping">
<summary>
Is the MoveHelper standing on a terrain too steep to stand on (Always false if IsOnGround false)
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.IsStuck">
<summary>
The MoveHelper is stuck and we can't get it out
</summary>
</member>
<member name="F:ShrimpleCharacterController.ShrimpleCharacterController.SkinWidth">
<summary>
To avoid getting stuck due to imprecision we shrink the bounds before checking and compensate for it later
</summary>
</member>
<member name="P:ShrimpleCharacterController.ShrimpleCharacterController.Bounds">
<summary>
The bounds of this MoveHelper generated from the TraceWidth and TraceHeight
</summary>
</member>
<member name="F:ShrimpleCharacterController.ShrimpleCharacterController.UnstuckTarget">
<summary>
If another MoveHelper moved at the same time and they're stuck, let this one know that the other already unstuck for us
</summary>
</member>
<member name="M:ShrimpleCharacterController.ShrimpleCharacterController.BuildTrace(BBox,Vector3,Vector3)">
<summary>
Casts the current bounds from to and returns the scene trace result
</summary>
<param name="bounds"></param>
<param name="from"></param>
<param name="to"></param>
<returns></returns>
</member>
<member name="M:ShrimpleCharacterController.ShrimpleCharacterController.Punch(Vector3@)">
<summary>
Detach the MoveHelper from the ground and launch it somewhere (Units per second)
</summary>
<param name="amount"></param>
</member>
<member name="M:ShrimpleCharacterController.ShrimpleCharacterController.Move(System.Boolean)">
<summary>
Apply the WishVelocity, update the Velocity and the Position of the GameObject by simulating the MoveHelper
</summary>
<param name="manualUpdate">Just calculate but don't update position</param>
</member>
<member name="M:ShrimpleCharacterController.ShrimpleCharacterController.Move(System.Single,System.Boolean)">
<summary>
Apply the WishVelocity, update the Velocity and the Position of the GameObject by simulating the MoveHelper
</summary>
<param name="delta">The time step</param>
<param name="manualUpdate">Just calculate but don't update position</param>
</member>
<member name="T:ShrimpleCharacterController.ShrimpleCharacterController.MoveHelperResult">
<summary>
Sometimes we have to update only the position but not the velocity (Like when climbing steps or getting unstuck) so we can't have Position rely only on Velocity
</summary>
</member>
<member name="M:ShrimpleCharacterController.ShrimpleCharacterController.TestPosition(Vector3,System.String)">
<summary>
Debug don't use
</summary>
<param name="position"></param>
<param name="title"></param>
<returns></returns>
</member>
<member name="M:ShrimpleCharacterController.Vector3Extensions.MoveTowards(Vector3,Vector3,System.Single)">
<summary>
Move a vector3 towards a goal by a fixed distance
</summary>
<param name="value"></param>
<param name="target"></param>
<param name="travelSpeed"></param>
<returns></returns>
</member>
<member name="M:ShrimpleCharacterController.Vector3Extensions.ProjectAndScale(Vector3,Vector3)">
<summary>
Project a vector along a plane (normal) and scale it back to its original length
</summary>
<param name="value"></param>
<param name="normal"></param>
<returns></returns>
</member>
</members>
</doc>

View File

@ -0,0 +1,57 @@
{
"scene.lastopened": {
"Value": "[\u0022scenes/walker_example.scene\u0022]",
"Timeout": 1732563082,
"DeleteAt": 0
},
"gizmo.settings": {
"Value": "{\u0022EditMode\u0022:\u0022position\u0022,\u0022Selection\u0022:true,\u0022ViewMode\u0022:\u00223d\u0022,\u0022GizmosEnabled\u0022:true,\u0022GizmoScale\u0022:1,\u0022GridSpacing\u0022:8,\u0022SnapToGrid\u0022:true,\u0022SnapToAngles\u0022:true,\u0022AngleSpacing\u0022:15,\u0022GlobalSpace\u0022:false,\u0022DebugActionGraphs\u0022:false}",
"Timeout": 1732563082,
"DeleteAt": 0
},
"scenes/flyer_example.scene.Viewport0": {
"Value": "{\u0022CameraPosition\u0022:\u0022-7143.974,-7143.975,10902.61\u0022,\u0022CameraRotation\u0022:\u0022-0.1464466,0.3535534,0.3535534,0.8535534\u0022,\u0022CameraOrthoHeight\u0022:1000}",
"Timeout": 1732471236,
"DeleteAt": 0
},
"scenes/walker_example.scene.Viewport0": {
"Value": "{\u0022CameraPosition\u0022:\u00224.097099,268.366,496.7835\u0022,\u0022CameraRotation\u0022:\u00220.2423258,0.2017571,-0.7292984,0.6072035\u0022,\u0022CameraOrthoHeight\u0022:1000}",
"Timeout": 1732563138,
"DeleteAt": 0
},
".Viewport0": {
"Value": "{\u0022CameraPosition\u0022:\u002266.49246,-768.0743,49.54514\u0022,\u0022CameraRotation\u0022:\u00220.1079748,0.1108001,-0.689514,0.7075558\u0022,\u0022CameraOrthoHeight\u0022:1000}",
"Timeout": 1732471755,
"DeleteAt": 0
},
"AssetBrowser.History.AssetsBrowser.ViewMode": {
"Value": "0",
"Timeout": 1732471206,
"DeleteAt": 0
},
"AssetBrowser.History.AssetsBrowser.ShowJunkFiles": {
"Value": "false",
"Timeout": 1732471206,
"DeleteAt": 0
},
"AssetBrowser.History.AssetsBrowser.ShowRecursiveFiles": {
"Value": "false",
"Timeout": 1732471206,
"DeleteAt": 0
},
"expand.dad296d6-935e-4779-b5ae-67a3a0d28ab6.MissingComponent": {
"Value": "false",
"Timeout": 1732471755,
"DeleteAt": 0
},
"SceneView.Viewport0.Settings": {
"Value": "{\u0022CameraPosition\u0022:\u00224.097099,268.366,496.7835\u0022,\u0022CameraRotation\u0022:\u00220.2423258,0.2017571,-0.7292984,0.6072035\u0022,\u0022View\u0022:0,\u0022RenderMode\u0022:0,\u0022WireframeMode\u0022:false,\u0022EnablePostProcessing\u0022:true,\u0022ShowGrid\u0022:true,\u0022GridOpacity\u0022:0.2,\u0022GridAxis\u0022:0,\u0022CameraOrthoHeight\u0022:1000}",
"Timeout": 1732563138,
"DeleteAt": 0
},
"SceneView.Layout": {
"Value": "{\u0022Layout\u0022:0,\u0022SplitterState\u0022:[]}",
"Timeout": 1732563082,
"DeleteAt": 0
}
}

View File

@ -0,0 +1 @@
1.0.75465

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

View File

@ -0,0 +1,121 @@
{
"__guid": "e78370eb-4e25-4b7f-bbf8-89f0fcbaa68b",
"GameObjects": [
{
"__guid": "048573b1-fa80-406a-a30d-93881e2b19c9",
"Flags": 0,
"Name": "debug_world",
"Enabled": true,
"__Prefab": "prefabs/debug_world.prefab",
"__PrefabVariables": {}
},
{
"__guid": "dad296d6-935e-4779-b5ae-67a3a0d28ab6",
"Flags": 0,
"Name": "Player",
"Position": "-171.0225,-113.5377,171.9933",
"Enabled": true,
"Components": [
{
"__type": "ShrimpleCharacterController.ShrimpleCharacterController",
"__guid": "fa127e8d-b05d-4e14-894d-d2977361591d",
"AirAcceleration": 1500,
"AirDeceleration": 700,
"Gravity": -850,
"GravityEnabled": false,
"GroundAcceleration": 1000,
"GroundDeceleration": 1500,
"GroundStickDistance": 12,
"GroundStickEnabled": false,
"IgnoreGroundSurface": false,
"IgnoreTags": "",
"IgnoreZ": false,
"IgnoreZWhenZero": true,
"ManuallyUpdate": true,
"MaxBounces": 5,
"MaxGroundAngle": 60,
"MaxUnstuckTries": 20,
"PushEnabled": false,
"PushTagsWeight": {
"player": 1
},
"ScaleAgainstWalls": true,
"StepDepth": 2,
"StepHeight": 12,
"StepsEnabled": false,
"TraceHeight": 72,
"TraceWidth": 16,
"UnstuckEnabled": true,
"UseSceneGravity": true
},
{
"__type": "ShrimpleCharacterController.ShrimpleFlyer",
"__guid": "e79bdc25-5a6f-4eb2-8a49-5f7aac27f8cd",
"RunSpeed": 2400,
"WalkSpeed": 800
},
{
"__type": "Sandbox.Citizen.CitizenAnimationHelper",
"__guid": "6bb6e1f8-1402-4b7b-9006-ea4866eb9e64",
"BodyWeight": 1,
"EyesWeight": 1,
"HeadWeight": 1,
"LookAtEnabled": false,
"Target": {
"_type": "component",
"component_id": "75a0dedf-07bc-4a29-9027-9e88625f7ba0",
"go": "768529ee-5ecc-4ddb-a81e-73fdb775baec",
"component_type": "SkinnedModelRenderer"
}
}
],
"Children": [
{
"__guid": "768529ee-5ecc-4ddb-a81e-73fdb775baec",
"Flags": 0,
"Name": "Model",
"Position": "0,0,0",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.SkinnedModelRenderer",
"__guid": "75a0dedf-07bc-4a29-9027-9e88625f7ba0",
"BodyGroups": 341,
"CreateBoneObjects": false,
"Model": "models/citizen/citizen.vmdl",
"RenderType": "On",
"Tint": "1,1,1,1",
"UseAnimGraph": true
}
]
}
]
}
],
"SceneProperties": {
"FixedUpdateFrequency": 50,
"MaxFixedUpdates": 5,
"NetworkFrequency": 30,
"NetworkInterpolation": true,
"ThreadedAnimation": true,
"TimeScale": 1,
"UseFixedUpdate": true,
"NavMesh": {
"Enabled": false,
"IncludeStaticBodies": true,
"IncludeKeyframedBodies": true,
"EditorAutoUpdate": true,
"AgentHeight": 64,
"AgentRadius": 16,
"AgentStepSize": 18,
"AgentMaxSlope": 40,
"ExcludedBodies": "",
"IncludedBodies": ""
}
},
"Title": "walker_example",
"Description": "",
"ResourceVersion": 1,
"__references": [],
"__version": 1
}

View File

@ -0,0 +1,146 @@
{
"__guid": "e78370eb-4e25-4b7f-bbf8-89f0fcbaa68b",
"GameObjects": [
{
"__guid": "048573b1-fa80-406a-a30d-93881e2b19c9",
"Flags": 0,
"Name": "debug_world",
"Enabled": true,
"__Prefab": "prefabs/debug_world.prefab",
"__PrefabVariables": {}
},
{
"__guid": "dad296d6-935e-4779-b5ae-67a3a0d28ab6",
"Flags": 0,
"Name": "Player",
"Position": "0,-49.46404,176.2773",
"Enabled": true,
"Components": [
{
"__type": "ShrimpleCharacterController.ShrimpleCharacterController",
"__guid": "fa127e8d-b05d-4e14-894d-d2977361591d",
"AirAcceleration": 250,
"AirDeceleration": 100,
"Gravity": -850,
"GravityEnabled": true,
"GroundAcceleration": 1000,
"GroundDeceleration": 2000,
"GroundStickDistance": 12,
"GroundStickEnabled": false,
"IgnoreGroundSurface": false,
"IgnoreTags": "",
"IgnoreZ": true,
"IgnoreZWhenZero": true,
"ManuallyUpdate": true,
"MaxBounces": 5,
"MaxGroundAngle": 60,
"MaxUnstuckTries": 20,
"PushEnabled": false,
"PushTagsWeight": {
"player": 1
},
"ScaleAgainstWalls": true,
"StepDepth": 2,
"StepHeight": 12,
"StepsEnabled": true,
"TraceHeight": 64,
"TraceWidth": 64,
"UnstuckEnabled": true,
"UseSceneGravity": true
},
{
"__type": "ShrimpleCharacterController.ShrimpleRoller",
"__guid": "c557f267-05dd-4185-be90-7d60757118ef",
"JumpStrength": 350,
"RunSpeed": 3000,
"WalkSpeed": 1000
}
],
"Children": [
{
"__guid": "768529ee-5ecc-4ddb-a81e-73fdb775baec",
"Flags": 0,
"Name": "Model",
"Position": "0,0,32",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.ModelRenderer",
"__guid": "13202fec-761f-46b0-9517-21a8662c39f3",
"BodyGroups": 18446744073709551615,
"MaterialOverride": "materials/editor/black_grid_8_doublesided.vmat",
"Model": "models/dev/sphere.vmdl",
"RenderType": "On",
"Tint": "1,1,1,1"
},
{
"__type": "Sandbox.TrailRenderer",
"__guid": "0c954483-095d-48f1-bb1c-47d90bbb6ae6",
"BlendMode": "Normal",
"CastShadows": false,
"Color": {
"color": [
{
"c": "1,1,1,0.5"
},
{
"t": 1,
"c": "1,1,1,0"
}
],
"alpha": []
},
"LifeTime": 3,
"MaxPoints": 256,
"Opaque": false,
"PointDistance": 4,
"Texturing": {
"WorldSpace": true,
"UnitsPerTexture": 10,
"Scale": 1
},
"Width": {
"rangey": "0,64",
"frames": [
{
"y": 1
},
{
"x": 1
}
]
},
"Wireframe": false
}
]
}
]
}
],
"SceneProperties": {
"FixedUpdateFrequency": 50,
"MaxFixedUpdates": 5,
"NetworkFrequency": 30,
"NetworkInterpolation": true,
"ThreadedAnimation": true,
"TimeScale": 1,
"UseFixedUpdate": true,
"NavMesh": {
"Enabled": false,
"IncludeStaticBodies": true,
"IncludeKeyframedBodies": true,
"EditorAutoUpdate": true,
"AgentHeight": 64,
"AgentRadius": 16,
"AgentStepSize": 18,
"AgentMaxSlope": 40,
"ExcludedBodies": "",
"IncludedBodies": ""
}
},
"Title": "walker_example",
"Description": "",
"ResourceVersion": 1,
"__references": [],
"__version": 1
}

View File

@ -0,0 +1,123 @@
{
"__guid": "e78370eb-4e25-4b7f-bbf8-89f0fcbaa68b",
"GameObjects": [
{
"__guid": "048573b1-fa80-406a-a30d-93881e2b19c9",
"Flags": 0,
"Name": "debug_world",
"Enabled": true,
"__Prefab": "prefabs/debug_world.prefab",
"__PrefabVariables": {}
},
{
"__guid": "dad296d6-935e-4779-b5ae-67a3a0d28ab6",
"Flags": 0,
"Name": "Player",
"Position": "-171.0225,-113.5377,171.9933",
"Enabled": true,
"Components": [
{
"__type": "ShrimpleCharacterController.ShrimpleCharacterController",
"__guid": "fa127e8d-b05d-4e14-894d-d2977361591d",
"AirAcceleration": 300,
"AirDeceleration": 0,
"Gravity": -850,
"GravityEnabled": true,
"GroundAcceleration": 1000,
"GroundDeceleration": 1500,
"GroundStickDistance": 12,
"GroundStickEnabled": true,
"IgnoreGroundSurface": false,
"IgnoreTags": "",
"IgnoreZ": true,
"IgnoreZWhenZero": true,
"ManuallyUpdate": true,
"MaxBounces": 5,
"MaxGroundAngle": 60,
"MaxUnstuckTries": 20,
"PushEnabled": false,
"PushTagsWeight": {
"player": 1
},
"ScaleAgainstWalls": true,
"StepDepth": 2,
"StepHeight": 12,
"StepsEnabled": true,
"TraceHeight": 72,
"TraceWidth": 16,
"UnstuckEnabled": true,
"UseSceneGravity": true
},
{
"__type": "Sandbox.Citizen.CitizenAnimationHelper",
"__guid": "6bb6e1f8-1402-4b7b-9006-ea4866eb9e64",
"BodyWeight": 1,
"EyesWeight": 1,
"HeadWeight": 1,
"LookAtEnabled": false,
"Target": {
"_type": "component",
"component_id": "75a0dedf-07bc-4a29-9027-9e88625f7ba0",
"go": "768529ee-5ecc-4ddb-a81e-73fdb775baec",
"component_type": "SkinnedModelRenderer"
}
},
{
"__type": "ShrimpleCharacterController.ShrimpleWalker",
"__guid": "21e48f2b-e808-42b7-83e6-83282972f187",
"DuckSpeed": 50,
"JumpStrength": 350,
"RunSpeed": 300,
"WalkSpeed": 100
}
],
"Children": [
{
"__guid": "768529ee-5ecc-4ddb-a81e-73fdb775baec",
"Flags": 0,
"Name": "Model",
"Position": "0,0,0",
"Enabled": true,
"Components": [
{
"__type": "Sandbox.SkinnedModelRenderer",
"__guid": "75a0dedf-07bc-4a29-9027-9e88625f7ba0",
"BodyGroups": 341,
"CreateBoneObjects": false,
"Model": "models/citizen/citizen.vmdl",
"RenderType": "On",
"Tint": "1,1,1,1",
"UseAnimGraph": true
}
]
}
]
}
],
"SceneProperties": {
"FixedUpdateFrequency": 50,
"MaxFixedUpdates": 5,
"NetworkFrequency": 30,
"NetworkInterpolation": true,
"ThreadedAnimation": true,
"TimeScale": 1,
"UseFixedUpdate": true,
"NavMesh": {
"Enabled": false,
"IncludeStaticBodies": true,
"IncludeKeyframedBodies": true,
"EditorAutoUpdate": true,
"AgentHeight": 64,
"AgentRadius": 16,
"AgentStepSize": 18,
"AgentMaxSlope": 40,
"ExcludedBodies": "",
"IncludedBodies": ""
}
},
"Title": "walker_example",
"Description": "",
"ResourceVersion": 1,
"__references": [],
"__version": 1
}

View File

@ -0,0 +1,5 @@
global using Sandbox;
global using System;
global using System.Collections.Generic;
global using System.Linq;
namespace ShrimpleCharacterController;

View File

@ -0,0 +1,68 @@
using Sandbox.Citizen;
namespace ShrimpleCharacterController;
[Hide]
public sealed class ShrimpleFlyer : Component
{
[RequireComponent]
public ShrimpleCharacterController Controller { get; set; }
[RequireComponent]
public CitizenAnimationHelper AnimationHelper { get; set; }
public SkinnedModelRenderer Renderer { get; set; }
public GameObject Camera { get; set; }
[Property]
[Range(400f, 1600f, 20f)]
public float WalkSpeed { get; set; } = 800f;
[Property]
[Range(800f, 4000f, 80f)]
public float RunSpeed { get; set; } = 2400f;
public Angles EyeAngles { get; set; }
protected override void OnStart()
{
base.OnStart();
Renderer = AnimationHelper.Target;
Camera = new GameObject(true, "Camera");
Camera.SetParent(GameObject);
var cameraComponent = Camera.Components.Create<CameraComponent>();
cameraComponent.ZFar = 32768f;
}
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
var isDucking = Input.Down("Duck");
var isRunning = Input.Down("Run");
var ascending = Input.Down("Jump") ? 1f : 0f;
var descending = Input.Down("Duck") ? -1f : 0f;
var wishSpeed = isRunning ? RunSpeed : WalkSpeed;
var wishDirection = (Input.AnalogMove + Vector3.Up * (ascending + descending)).Normal * EyeAngles.ToRotation();
Controller.WishVelocity = wishDirection * wishSpeed;
Controller.Move();
AnimationHelper.WithWishVelocity(Controller.WishVelocity);
AnimationHelper.WithVelocity(Controller.Velocity);
AnimationHelper.IsGrounded = Controller.IsOnGround;
}
protected override void OnUpdate()
{
base.OnUpdate();
EyeAngles += Input.AnalogLook;
EyeAngles = EyeAngles.WithPitch(MathX.Clamp(EyeAngles.pitch, -10f, 40f));
Renderer.WorldRotation = Rotation.Slerp(Renderer.WorldRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 5f);
var cameraOffset = Vector3.Up * 70f + Vector3.Backward * 220f;
Camera.WorldRotation = EyeAngles.ToRotation();
Camera.LocalPosition = cameraOffset * Camera.WorldRotation;
}
}

View File

@ -0,0 +1,71 @@
namespace ShrimpleCharacterController;
[Hide]
public sealed class ShrimpleRoller : Component
{
[RequireComponent]
public ShrimpleCharacterController Controller { get; set; }
public ModelRenderer Renderer { get; set; }
public GameObject Camera { get; set; }
[Property]
[Range(500f, 2000f, 100f)]
public float WalkSpeed { get; set; } = 1000f;
[Property]
[Range(1000f, 5000f, 200f)]
public float RunSpeed { get; set; } = 3000f;
[Property]
[Range(200f, 500f, 20f)]
public float JumpStrength { get; set; } = 350f;
public Angles EyeAngles { get; set; }
protected override void OnStart()
{
base.OnStart();
Renderer = Components.Get<ModelRenderer>(FindMode.EnabledInSelfAndDescendants);
Camera = new GameObject(true, "Camera");
Camera.SetParent(GameObject);
var cameraComponent = Camera.Components.Create<CameraComponent>();
cameraComponent.ZFar = 32768f;
}
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
var wishDirection = Input.AnalogMove.Normal * Rotation.FromYaw(EyeAngles.yaw);
var isDucking = Input.Down("Duck");
var isRunning = Input.Down("Run");
var wishSpeed = isRunning ? RunSpeed : WalkSpeed;
Controller.WishVelocity = wishDirection * wishSpeed;
Controller.Move();
if (Input.Pressed("Jump") && Controller.IsOnGround)
Controller.Punch(Vector3.Up * JumpStrength);
}
protected override void OnUpdate()
{
base.OnUpdate();
EyeAngles += Input.AnalogLook;
EyeAngles = EyeAngles.WithPitch(MathX.Clamp(EyeAngles.pitch, -10f, 40f));
float pitchRotation = Controller.Velocity.x * Time.Delta;
float rollRotation = -Controller.Velocity.y * Time.Delta;
var ballPitch = Rotation.FromPitch(pitchRotation);
var ballRoll = Rotation.FromRoll(rollRotation);
Renderer.WorldRotation = ballPitch * ballRoll * Renderer.WorldRotation;
var cameraOffset = Vector3.Up * 70f + Vector3.Backward * 260f;
Camera.WorldRotation = EyeAngles.ToRotation();
Camera.LocalPosition = cameraOffset * Camera.WorldRotation;
}
}

View File

@ -0,0 +1,84 @@
using Sandbox.Citizen;
namespace ShrimpleCharacterController;
[Hide]
public sealed class ShrimpleWalker : Component
{
[RequireComponent]
public ShrimpleCharacterController Controller { get; set; }
[RequireComponent]
public CitizenAnimationHelper AnimationHelper { get; set; }
public SkinnedModelRenderer Renderer { get; set; }
public GameObject Camera { get; set; }
[Property]
[Range(50f, 200f, 10f)]
public float WalkSpeed { get; set; } = 100f;
[Property]
[Range(100f, 500f, 20f)]
public float RunSpeed { get; set; } = 300f;
[Property]
[Range(25f, 100f, 5f)]
public float DuckSpeed { get; set; } = 50f;
[Property]
[Range(200f, 500f, 20f)]
public float JumpStrength { get; set; } = 350f;
public Angles EyeAngles { get; set; }
protected override void OnStart()
{
base.OnStart();
Renderer = Components.Get<SkinnedModelRenderer>(FindMode.EverythingInSelfAndDescendants);
Camera = new GameObject(true, "Camera");
Camera.SetParent(GameObject);
var cameraComponent = Camera.Components.Create<CameraComponent>();
cameraComponent.ZFar = 32768f;
}
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
var wishDirection = Input.AnalogMove.Normal * Rotation.FromYaw(EyeAngles.yaw);
var isDucking = Input.Down("Duck");
var isRunning = Input.Down("Run");
var wishSpeed = isDucking ? DuckSpeed :
isRunning ? RunSpeed : WalkSpeed;
Controller.WishVelocity = wishDirection * wishSpeed;
Controller.Move();
if (Input.Pressed("Jump") && Controller.IsOnGround)
{
Controller.Punch(Vector3.Up * JumpStrength);
AnimationHelper?.TriggerJump();
}
if (!AnimationHelper.IsValid()) return;
AnimationHelper.WithWishVelocity(Controller.WishVelocity);
AnimationHelper.WithVelocity(Controller.Velocity);
AnimationHelper.DuckLevel = isDucking ? 1f : 0f;
AnimationHelper.IsGrounded = Controller.IsOnGround;
}
protected override void OnUpdate()
{
base.OnUpdate();
EyeAngles += Input.AnalogLook;
EyeAngles = EyeAngles.WithPitch(MathX.Clamp(EyeAngles.pitch, -10f, 40f));
Renderer.WorldRotation = Rotation.Slerp(Renderer.WorldRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 5f);
var cameraOffset = Vector3.Up * 70f + Vector3.Backward * 220f;
Camera.WorldRotation = EyeAngles.ToRotation();
Camera.LocalPosition = cameraOffset * Camera.WorldRotation;
}
}

View File

@ -0,0 +1,755 @@
namespace ShrimpleCharacterController;
[Icon("nordic_walking")]
public class ShrimpleCharacterController : Component
{
/// <summary>
/// Manually update this by calling Move() or let it always be simulated
/// </summary>
[Property]
[Group("Options")]
public bool ManuallyUpdate { get; set; } = true;
/// <summary>
/// If pushing against a wall, scale the velocity based on the wall's angle (False is useful for NPCs that get stuck on corners)
/// </summary>
[Property]
[Group("Options")]
public bool ScaleAgainstWalls { get; set; } = true;
[Sync]
float _traceWidth { get; set; } = 16f;
/// <summary>
/// Width of our trace
/// </summary>
[Property]
[Group("Trace")]
[Range(1f, 64f, 1f, true, true)]
public float TraceWidth
{
get => _traceWidth;
set
{
_traceWidth = value;
Bounds = BuildBounds();
_shrunkenBounds = Bounds.Grow(-SkinWidth);
}
}
[Sync]
float _traceHeight { get; set; } = 72f;
/// <summary>
/// Height of our trace
/// </summary>
[Property]
[Group("Trace")]
[Range(1f, 256f, 1f, true, true)]
public float TraceHeight
{
get => _traceHeight;
set
{
_traceHeight = value;
Bounds = BuildBounds();
_shrunkenBounds = Bounds.Grow(-SkinWidth);
}
}
/// <summary>
/// Which tags it should ignore
/// </summary>
[Property]
[Group("Trace")]
public TagSet IgnoreTags { get; set; } = new TagSet();
/// <summary>
/// Max amount of trace calls whenever the simulation doesn't reach its target (Slide and collide bounces)
/// </summary>
[Property]
[Group("Trace")]
[Range(1, 20, 1, true, true)]
public int MaxBounces { get; set; } = 5;
/// <summary>
/// How fast you accelerate while on the ground (Units per second)
/// </summary>
[Property]
[Group("Movement")]
[Range(0f, 3000f, 10f, false)]
[HideIf("GroundStickEnabled", false)]
public float GroundAcceleration { get; set; } = 1000f;
/// <summary>
/// How fast you decelerate while on the ground (Units per second)
/// </summary>
[Property]
[Group("Movement")]
[Range(0f, 3000f, 10f, false)]
[HideIf("GroundStickEnabled", false)]
public float GroundDeceleration { get; set; } = 1500f;
/// <summary>
/// How fast you accelerate while in the air (Units per second)
/// </summary>
[Property]
[Group("Movement")]
[Range(0f, 3000f, 10f, false)]
public float AirAcceleration { get; set; } = 300f;
/// <summary>
/// How fast you decelerate while in the air (Units per second)
/// </summary>
[Property]
[Group("Movement")]
[Range(0f, 3000f, 10f, false)]
public float AirDeceleration { get; set; } = 0f;
/// <summary>
/// Do we ignore the friction of the surface you're standing on or not?
/// </summary>
[Property]
[Group("Movement")]
public bool IgnoreGroundSurface { get; set; } = false;
/// <summary>
/// Is this MoveHelper meant for horizontal grounded movement? (false = For flying or noclip)
/// </summary>
[Property]
[Group("Movement")]
public bool IgnoreZ { get; set; } = true;
/// <summary>
/// Do we ignore Z when it's near 0 (So that gravity affects you when not moving)
/// </summary>
[Property]
[Title("Ignore Z When Zero")]
[Group("Movement")]
[HideIf("IgnoreZ", true)]
public bool IgnoreZWhenZero { get; set; } = true;
/// <summary>
/// Tolerance from a 90° surface before it's considered a wall (Ex. Tolerance 1 = Between 89° and 91° can be a wall, 0.1 = 89.9° to 90.1°)
/// </summary>
[Group("Movement")]
[Property]
[Range(0f, 10f, 0.1f, false)]
public float WallTolerance { get; set; } = 1f;
/// <summary>
/// Player feels like it's gripping walls too much? Try more Grip Factor Reduction!
/// </summary>
[Group("Movement")]
[Property]
[Range(1f, 10f, 0.1f, true)]
public float GripFactorReduction { get; set; } = 1f;
/// <summary>
/// Stick the MoveHelper to the ground (IsOnGround will default to false if disabled)
/// </summary>
[ToggleGroup("GroundStickEnabled")]
[Property]
public bool GroundStickEnabled { get; set; } = true;
/// <summary>
/// How steep terrain can be for you to stand on without slipping
/// </summary>
[Property]
[Group("GroundStickEnabled")]
[Range(0f, 89f, 1f, true, true)]
public float MaxGroundAngle { get; set; } = 60f;
/// <summary>
/// How far from the ground the MoveHelper is going to stick (Useful for going down stairs!)
/// </summary>
[Property]
[Group("GroundStickEnabled")]
[Range(1f, 32f, 1f, false)]
public float GroundStickDistance { get; set; } = 12f;
/// <summary>
/// Enable steps climbing (+1 Trace call)
/// </summary>
[ToggleGroup("StepsEnabled")]
[Property]
public bool StepsEnabled { get; set; } = true;
/// <summary>
/// How high steps can be for you to climb on
/// </summary>
[Group("StepsEnabled")]
[Property]
[Range(1f, 32f, 1f, false)]
public float StepHeight { get; set; } = 12f;
/// <summary>
/// How deep it checks for steps (Minimum depth)
/// </summary>
[Group("StepsEnabled")]
[Property]
[Range(0.1f, 8f, 0.1f, false)]
public float StepDepth { get; set; } = 2f;
/// <summary>
/// Tolerance from a 90° surface before it's considered a valid step (Ex. Tolerance 1 = Between 89° and 91° can be a step, 0.1 = 89.9° to 90.1°)
/// </summary>
[Group("StepsEnabled")]
[Property]
[Range(0f, 10f, 0.1f, false)]
public float StepTolerance { get; set; } = 1f;
/// <summary>
/// Enable to ability to walk on a surface that's too steep if it's equal or smaller than a step (+1 Trace call when on steep terrain)
/// </summary>
[Group("StepsEnabled")]
[Property]
public bool PseudoStepsEnabled { get; set; } = true;
/// <summary>
/// Instead of colliding with these tags the MoveHelper will be pushed away (Make sure the tags are in IgnoreTags as well!)
/// </summary>
[ToggleGroup("PushEnabled")]
[Property]
public bool PushEnabled { get; set; } = false;
[Sync]
Dictionary<string, float> _pushTagsWeight { get; set; } = new Dictionary<string, float>() { { "player", 1f } };
/// <summary>
/// Which tags will push this MoveHelper away and with how much force (Make sure they are also included in IgnoreTags!) (+1 Trace call)
/// </summary>
[Property]
[Group("PushEnabled")]
public Dictionary<string, float> PushTagsWeight
{
get => _pushTagsWeight;
set
{
_pushTagsWeight = value;
_pushTags = BuildPushTags();
}
}
/// <summary>
/// Apply gravity to this MoveHelper when not on the ground
/// </summary>
[ToggleGroup("GravityEnabled")]
[Property]
public bool GravityEnabled { get; set; } = true;
/// <summary>
/// Use the scene's gravity or our own
/// </summary>
[Property]
[Group("GravityEnabled")]
public bool UseSceneGravity { get; set; } = true;
/// <summary>
/// Units per second squared (Default is -850f)
/// </summary>
[Property]
[Group("GravityEnabled")]
[Range(-2000, 2000, 1, false)]
[HideIf("UseSceneGravity", true)]
public float Gravity { get; set; } = -850f;
/// <summary>
/// Check if the MoveHelper is stuck and try to get it to unstuck (+Trace calls if stuck)
/// </summary>
[ToggleGroup("UnstuckEnabled")]
[Property]
public bool UnstuckEnabled { get; set; } = true;
/// <summary>
/// How many trace calls it will attempt to get the MoveHelper unstuck
/// </summary>
[Property]
[Group("UnstuckEnabled")]
[Range(1, 50, 1, false)]
public int MaxUnstuckTries { get; set; } = 20;
/// <summary>
/// The simulated target velocity for our MoveHelper (Units per second, we apply Time.Delta inside)
/// </summary>
[Sync] public Vector3 WishVelocity { get; set; }
/// <summary>
/// The resulting velocity after the simulation is done (Units per second)
/// </summary>
[Sync] public Vector3 Velocity { get; set; }
/// <summary>
/// Is the MoveHelper currently touching the ground
/// </summary>
[Sync] public bool IsOnGround { get; set; }
/// The current ground normal you're standing on (Always Vector3.Zero if IsOnGround false)
/// </summary>
public Vector3 GroundNormal { get; private set; } = Vector3.Zero;
/// <summary>
/// The current ground angle you're standing on (Always 0f if IsOnGround false)
/// </summary>
public float GroundAngle => Vector3.GetAngle(GroundNormal, Vector3.Up);
/// <summary>
/// The current surface you're standing on
/// </summary>
public Surface GroundSurface { get; private set; }
/// <summary>
/// The gameobject you're currently standing on
/// </summary>
public GameObject GroundObject { get; set; }
/// <summary>
/// Is the MoveHelper currently pushing against a wall
/// </summary>
public bool IsPushingAgainstWall { get; private set; }
/// <summary>
/// The current wall normal you're pushing against (Always Vector3.Zero if IsPushingAgainstWall false)
/// </summary>
public Vector3 WallNormal { get; private set; } = Vector3.Zero;
/// <summary>
/// The gameobject you're currently pushing on
/// </summary>
public GameObject WallObject { get; set; }
/// <summary>
/// Is the MoveHelper standing on a terrain too steep to stand on (Always false if IsOnGround false)
/// </summary>
[Sync] public bool IsSlipping { get; private set; } // TODO IMPLEMENT
/// <summary>
/// The MoveHelper is stuck and we can't get it out
/// </summary>
[Sync] public bool IsStuck { get; private set; }
/// <summary>
/// To avoid getting stuck due to imprecision we shrink the bounds before checking and compensate for it later
/// </summary>
public float SkinWidth;
/// <summary>
/// The bounds of this MoveHelper generated from the TraceWidth and TraceHeight
/// </summary>
public BBox Bounds { get; set; }
private BBox _shrunkenBounds;
private string[] _pushTags;
private Vector3 _lastVelocity;
/// <summary>
/// If another MoveHelper moved at the same time and they're stuck, let this one know that the other already unstuck for us
/// </summary>
public ShrimpleCharacterController UnstuckTarget;
protected override void OnStart()
{
SkinWidth = Math.Min(Math.Max(0.1f, TraceWidth * 0.05f), GroundStickDistance); // SkinWidth is 5% of the total width
Bounds = BuildBounds();
_shrunkenBounds = Bounds.Grow(-SkinWidth);
_pushTags = BuildPushTags();
}
protected override void DrawGizmos()
{
if (Gizmo.IsSelected)
{
Gizmo.GizmoDraw draw = Gizmo.Draw;
draw.Color = Color.Blue;
draw.LineBBox(BuildBounds());
}
}
private BBox BuildBounds()
{
return new BBox(new Vector3(-TraceWidth / 2, -TraceWidth / 2f, 0f), new Vector3(TraceWidth / 2f, TraceWidth / 2f, TraceHeight));
}
private string[] BuildPushTags()
{
return PushTagsWeight.Keys.ToArray();
}
/// <summary>
/// Casts the current bounds from to and returns the scene trace result
/// </summary>
/// <param name="bounds"></param>
/// <param name="from"></param>
/// <param name="to"></param>
/// <returns></returns>
public SceneTraceResult BuildTrace(BBox bounds, Vector3 from, Vector3 to)
{
return Game.SceneTrace.Box(bounds, from, to)
.IgnoreGameObjectHierarchy(GameObject)
.WithoutTags(IgnoreTags)
.Run();
}
private SceneTraceResult BuildPushTrace(BBox bounds, Vector3 from, Vector3 to)
{
return Game.SceneTrace.Box(bounds, from, to)
.IgnoreGameObjectHierarchy(GameObject)
.WithAnyTags(_pushTags) // Check for only the push tags
.Run();
}
/// <summary>
/// Detach the MoveHelper from the ground and launch it somewhere (Units per second)
/// </summary>
/// <param name="amount"></param>
public void Punch(in Vector3 amount)
{
if (amount.z < 10f) return; // Get out with that weak crap
IsOnGround = false;
Velocity += amount;
}
/// <summary>
/// Apply the WishVelocity, update the Velocity and the Position of the GameObject by simulating the MoveHelper
/// </summary>
/// <param name="manualUpdate">Just calculate but don't update position</param>
public MoveHelperResult Move(bool manualUpdate = false) => Move(Time.Delta, manualUpdate);
/// <summary>
/// Apply the WishVelocity, update the Velocity and the Position of the GameObject by simulating the MoveHelper
/// </summary>
/// <param name="delta">The time step</param>
/// <param name="manualUpdate">Just calculate but don't update position</param>
public MoveHelperResult Move(float delta, bool manualUpdate = false)
{
var goalVelocity = CalculateGoalVelocity(delta); // Calculate the goal velocity using our Acceleration and Deceleration values
// KNOWN ISSUE: Velocity starts to build up to massive amounts when trying to climb terrain too steep?
// SIMULATE PUSH FORCES //
if (PushEnabled)
{
var pushTrace = BuildPushTrace(Bounds, WorldPosition, WorldPosition); // Build a trace but using the Push tags instead of the Ignore tags
if (pushTrace.Hit) // We're inside any of the push tags
{
foreach (var tag in pushTrace.GameObject.Tags)
{
if (PushTagsWeight.TryGetValue(tag, out var tagWeight))
{
var otherPosition = pushTrace.GameObject.WorldPosition.WithZ(WorldPosition.z); // Only horizontal pushing
var pushDirection = (otherPosition - WorldPosition).Normal;
var pushVelocity = pushDirection * tagWeight * 50f; // I find 50 u/s to be a good amount to push if the weight is 1.0 (!!!)
goalVelocity -= pushVelocity;
}
}
}
}
var moveHelperResult = CollideAndSlide(goalVelocity, WorldPosition, delta); // Simulate the MoveHelper
var finalPosition = moveHelperResult.Position;
var finalVelocity = moveHelperResult.Velocity;
// SIMULATE GRAVITY //
if (GravityEnabled && Gravity != 0f)
{
if (!IsOnGround || IsSlipping || !GroundStickEnabled)
{
var gravityAmount = UseSceneGravity ? Scene.PhysicsWorld.Gravity.z : Gravity;
var gravity = gravityAmount * Vector3.Up * delta;
var gravityResult = CollideAndSlide(gravity, moveHelperResult.Position, delta, gravityPass: true); // Apply and simulate the gravity step
finalPosition = gravityResult.Position;
finalVelocity += gravityResult.Velocity;
}
}
_lastVelocity = Velocity * delta;
if (!manualUpdate)
{
Velocity = finalVelocity;
WorldPosition = finalPosition; // Actually updating the position is "expensive" so we only do it once at the end
}
return new MoveHelperResult(finalPosition, finalVelocity);
}
/// <summary>
/// Sometimes we have to update only the position but not the velocity (Like when climbing steps or getting unstuck) so we can't have Position rely only on Velocity
/// </summary>
public struct MoveHelperResult
{
public Vector3 Position;
public Vector3 Velocity;
public MoveHelperResult(Vector3 position, Vector3 velocity)
{
Position = position;
Velocity = velocity;
}
}
private MoveHelperResult CollideAndSlide(Vector3 velocity, Vector3 position, float delta, int depth = 0, bool gravityPass = false) =>
CollideAndSlide(new MoveHelperResult(position, velocity), delta, depth, gravityPass);
private MoveHelperResult CollideAndSlide(MoveHelperResult current, float delta, int depth = 0, bool gravityPass = false)
{
if (depth >= MaxBounces)
return current;
var velocity = current.Velocity * delta; // I like to set Velocity as units/second but we have to deal with units/tick here
var position = current.Position;
// GROUND AND UNSTUCK CHECK //
if (depth == 0) // Only check for the first step since it's impossible to get stuck on other steps
{
var groundTrace = BuildTrace(_shrunkenBounds, position, position + Vector3.Down * GroundStickDistance);
if (groundTrace.StartedSolid)
{
IsStuck = true;
if (UnstuckEnabled)
{
if (UnstuckTarget == null)
{
IsStuck = !TryUnstuck(position, out var result);
if (!IsStuck)
{
position = result; // Update the new position
if (groundTrace.GameObject != null)
if (groundTrace.GameObject.Components.TryGet<ShrimpleCharacterController>(out var otherHelper))
otherHelper.UnstuckTarget = this; // We already solved this, no need to unstuck the other helper
}
else
{
return new MoveHelperResult(position, Vector3.Zero); // Mission failed, bail out!
}
}
else
{
UnstuckTarget = null; // Alright the other MoveHelper got us unstuck so just do nothing
}
}
}
else
{
var hasLanded = !IsOnGround && Velocity.z <= 0f && groundTrace.Hit && groundTrace.Distance <= SkinWidth * 2f; // Wasn't on the ground and now is
var isGrounded = IsOnGround && groundTrace.Hit; // Was already on the ground and still is, this helps stick when going down stairs
IsOnGround = hasLanded || isGrounded;
GroundSurface = IsOnGround ? groundTrace.Surface : null;
GroundNormal = IsOnGround ? groundTrace.Normal : Vector3.Up;
GroundObject = IsOnGround ? groundTrace.GameObject : null;
IsSlipping = IsOnGround && GroundAngle > MaxGroundAngle;
if (IsSlipping && !gravityPass && velocity.z > 0f)
velocity = velocity.WithZ(0f); // If we're slipping ignore any extra velocity we had
if (IsOnGround && GroundStickEnabled && !IsSlipping)
{
position = groundTrace.EndPosition + Vector3.Up * SkinWidth; // Place on the ground
velocity = Vector3.VectorPlaneProject(velocity, GroundNormal); // Follow the ground you're on without projecting Z
}
IsStuck = false;
}
}
if (velocity.IsNearlyZero(0.01f)) // Not worth continuing, reduces small stutter
{
return new MoveHelperResult(position, Vector3.Zero);
}
var toTravel = velocity.Length + SkinWidth;
var targetPosition = position + velocity.Normal * toTravel;
var travelTrace = BuildTrace(_shrunkenBounds, position, targetPosition);
if (travelTrace.Hit)
{
var travelled = velocity.Normal * Math.Max(travelTrace.Distance - SkinWidth, 0f);
var leftover = velocity - travelled; // How much leftover velocity still needs to be simulated
var angle = Vector3.GetAngle(Vector3.Up, travelTrace.Normal);
if (toTravel >= SkinWidth && travelTrace.Distance < SkinWidth)
travelled = Vector3.Zero;
if (angle <= MaxGroundAngle) // Terrain we can walk on
{
if (gravityPass || !IsOnGround)
leftover = Vector3.VectorPlaneProject(leftover, travelTrace.Normal); // Don't project the vertical velocity after landing else it boosts your horizontal velocity
else
leftover = leftover.ProjectAndScale(travelTrace.Normal); // Project the velocity along the terrain
IsPushingAgainstWall = false;
WallObject = null;
}
else
{
var climbedStair = false;
if (angle >= 90f - WallTolerance && angle <= 90f + WallTolerance) // Check for walls
IsPushingAgainstWall = true; // We're pushing against a wall
if (StepsEnabled)
{
var isStep = angle >= 90f - StepTolerance && angle <= 90f + StepTolerance;
if (isStep || PseudoStepsEnabled) // Check for steps
{
if (IsOnGround) // Stairs VVV
{
var stepHorizontal = velocity.WithZ(0f).Normal * StepDepth; // How far in front we're looking for steps
var stepVertical = Vector3.Up * StepHeight; // How high we're looking for steps
var stepTrace = BuildTrace(_shrunkenBounds, travelTrace.EndPosition + stepHorizontal + stepVertical, travelTrace.EndPosition + stepHorizontal);
var stepAngle = Vector3.GetAngle(stepTrace.Normal, Vector3.Up);
if (!stepTrace.StartedSolid && stepTrace.Hit && stepAngle <= MaxGroundAngle) // We found a step!
{
if (isStep || !IsSlipping && PseudoStepsEnabled)
{
var stepDistance = stepTrace.EndPosition - travelTrace.EndPosition;
var stepTravelled = Vector3.Up * stepDistance;
position += stepTravelled; // Offset our position by the height of the step climbed
climbedStair = true;
IsPushingAgainstWall = false; // Nevermind, we're not against a wall, we climbed a step!
WallObject = null;
}
}
}
}
}
if (IsPushingAgainstWall)
{
// Scale our leftover velocity based on the angle of approach relative to the wall
// (Perpendicular = 0%, Parallel = 100%)
var scale = ScaleAgainstWalls ? 1f - Vector3.Dot(-travelTrace.Normal.Normal / GripFactorReduction, velocity.Normal) : 1f;
var wallLeftover = ScaleAgainstWalls ? Vector3.VectorPlaneProject(leftover, travelTrace.Normal.Normal) : leftover.ProjectAndScale(travelTrace.Normal.Normal);
leftover = (wallLeftover * scale).WithZ(wallLeftover.z);
WallObject = travelTrace.GameObject;
WallNormal = travelTrace.Normal;
}
else
{
if (!climbedStair)
{
var scale = IsSlipping ? 1f : 1f - Vector3.Dot(-travelTrace.Normal / GripFactorReduction, velocity.Normal);
leftover = ScaleAgainstWalls ? Vector3.VectorPlaneProject(leftover, travelTrace.Normal) * scale : leftover.ProjectAndScale(travelTrace.Normal);
}
}
}
if (travelled.Length <= 0.01f && leftover.Length <= 0.01f)
return new MoveHelperResult(position + travelled, travelled / delta);
var newResult = CollideAndSlide(new MoveHelperResult(position + travelled, leftover / delta), delta, depth + 1, gravityPass); // Simulate another bounce for the leftover velocity from the latest position
var currentResult = new MoveHelperResult(newResult.Position, travelled / delta + newResult.Velocity); // Use the new bounce's position and combine the velocities
return currentResult;
}
if (depth == 0 && !gravityPass)
{
IsPushingAgainstWall = false;
WallObject = null;
}
return new MoveHelperResult(position + velocity, velocity / delta); // We didn't hit anything? Ok just keep going then :-)
}
private float CalculateGoalSpeed(Vector3 wishVelocity, Vector3 velocity, bool isAccelerating, float delta)
{
float goalSpeed;
var isSameDirection = velocity.IsNearlyZero(1f) || Vector3.Dot(wishVelocity.WithZ(0f).Normal, velocity.WithZ(0f).Normal) >= 0f; // Is our wishVelocity roughly moving towards our velocity already?
var acceleration = IsOnGround ? GroundAcceleration : AirAcceleration;
var deceleration = IsOnGround ? GroundDeceleration : AirDeceleration;
if (isAccelerating)
goalSpeed = acceleration;
else
goalSpeed = !isSameDirection ? Math.Max(acceleration, deceleration) : deceleration; // Makes movement more responsive especially for flying or rolling
if (!IgnoreGroundSurface && GroundSurface != null)
goalSpeed *= GroundSurface.Friction; // Take into account the ground's friction
goalSpeed *= delta;
return goalSpeed;
}
private Vector3 CalculateGoalVelocity(float delta)
{
bool shouldIgnoreZ = IgnoreZ || (IgnoreZWhenZero && WishVelocity.z.AlmostEqual(0f));
var wishVelocity = shouldIgnoreZ ? (WishVelocity.Normal * WishVelocity.Length).WithZ(Velocity.z) : WishVelocity;
var isAccelerating = shouldIgnoreZ ? wishVelocity.WithZ(0f).Length >= Velocity.WithZ(0f).Length : wishVelocity.Length >= Velocity.Length;
var goalSpeed = CalculateGoalSpeed(wishVelocity, Velocity, isAccelerating, delta);
var goalVelocity = Velocity.MoveTowards(wishVelocity, goalSpeed);
return shouldIgnoreZ ? goalVelocity.WithZ(Velocity.z) : goalVelocity;
}
public bool TryUnstuck(Vector3 position, out Vector3 result)
{
var velocityLength = _lastVelocity.Length + SkinWidth;
var startPos = position - _lastVelocity.Normal * velocityLength; // Try undoing the last velocity 1st
var endPos = position;
for (int i = 0; i < MaxUnstuckTries + 1; i++)
{
if (i == 1)
startPos = position + Vector3.Up * 2f; // Try going up 2nd
if (i > 1)
startPos = position + Vector3.Random.Normal * ((float)i / 2f); // Start randomly checking 3rd
var unstuckTrace = BuildTrace(_shrunkenBounds, startPos, endPos);
if (!unstuckTrace.StartedSolid)
{
result = unstuckTrace.EndPosition - _lastVelocity.Normal * SkinWidth;
return true;
}
}
result = position;
return false;
}
/// <summary>
/// Debug don't use
/// </summary>
/// <param name="position"></param>
/// <param name="title"></param>
/// <returns></returns>
private bool TestPosition(Vector3 position, string title)
{
var testTrace = BuildTrace(_shrunkenBounds, position, position);
if (testTrace.StartedSolid)
{
Log.Info($"[{RealTime.Now}]{title} {GameObject.Name} started solid at {position} against {testTrace.GameObject}");
return true;
}
return false;
}
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
if (!ManuallyUpdate && Active)
Move();
}
}

View File

@ -0,0 +1,40 @@
namespace ShrimpleCharacterController;
public static class Vector3Extensions
{
/// <summary>
/// Move a vector3 towards a goal by a fixed distance
/// </summary>
/// <param name="value"></param>
/// <param name="target"></param>
/// <param name="travelSpeed"></param>
/// <returns></returns>
public static Vector3 MoveTowards( this Vector3 value, Vector3 target, float travelSpeed )
{
var difference = target - value;
var distance = difference.Length;
var normal = difference.Normal;
if ( distance <= travelSpeed || distance == 0f )
{
return target;
}
return value + normal * travelSpeed;
}
/// <summary>
/// Project a vector along a plane (normal) and scale it back to its original length
/// </summary>
/// <param name="value"></param>
/// <param name="normal"></param>
/// <returns></returns>
public static Vector3 ProjectAndScale( this Vector3 value, Vector3 normal )
{
var length = value.Length;
value = Vector3.VectorPlaneProject( value, normal ).Normal;
value *= length;
return value;
}
}

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Small Fish
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,34 @@
{
"Defaults": {
"solid": "Collide",
"trigger": "Trigger",
"ladder": "Ignore",
"water": "Trigger"
},
"Pairs": [
{
"a": "solid",
"b": "solid",
"r": "Collide"
},
{
"a": "trigger",
"b": "playerclip",
"r": "Ignore"
},
{
"a": "trigger",
"b": "solid",
"r": "Trigger"
},
{
"a": "playerclip",
"b": "solid",
"r": "Collide"
}
],
"__guid": "3f8027f2-5728-4178-a563-2be1da260457",
"__schema": "configdata",
"__type": "CollisionRules",
"__version": 1
}

View File

@ -0,0 +1,194 @@
{
"Actions": [
{
"Name": "Forward",
"KeyboardCode": "W",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Backward",
"KeyboardCode": "S",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Left",
"KeyboardCode": "A",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Right",
"KeyboardCode": "D",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Jump",
"KeyboardCode": "space",
"GamepadCode": "A",
"GroupName": "Movement"
},
{
"Name": "Run",
"KeyboardCode": "shift",
"GamepadCode": "LeftJoystickButton",
"GroupName": "Movement"
},
{
"Name": "Walk",
"KeyboardCode": "alt",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Duck",
"KeyboardCode": "ctrl",
"GamepadCode": "B",
"GroupName": "Movement"
},
{
"Name": "attack1",
"KeyboardCode": "mouse1",
"GamepadCode": "RightTrigger",
"GroupName": "Actions"
},
{
"Name": "attack2",
"KeyboardCode": "mouse2",
"GamepadCode": "LeftTrigger",
"GroupName": "Actions"
},
{
"Name": "reload",
"KeyboardCode": "r",
"GamepadCode": "X",
"GroupName": "Actions"
},
{
"Name": "use",
"KeyboardCode": "e",
"GamepadCode": "Y",
"GroupName": "Actions"
},
{
"Name": "Slot1",
"KeyboardCode": "1",
"GamepadCode": "DpadWest",
"GroupName": "Inventory"
},
{
"Name": "Slot2",
"KeyboardCode": "2",
"GamepadCode": "DpadEast",
"GroupName": "Inventory"
},
{
"Name": "Slot3",
"KeyboardCode": "3",
"GamepadCode": "DpadSouth",
"GroupName": "Inventory"
},
{
"Name": "Slot4",
"KeyboardCode": "4",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot5",
"KeyboardCode": "5",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot6",
"KeyboardCode": "6",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot7",
"KeyboardCode": "7",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot8",
"KeyboardCode": "8",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot9",
"KeyboardCode": "9",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot0",
"KeyboardCode": "0",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "SlotPrev",
"KeyboardCode": "mouse4",
"GamepadCode": "SwitchLeftBumper",
"GroupName": "Inventory"
},
{
"Name": "SlotNext",
"KeyboardCode": "mouse5",
"GamepadCode": "SwitchRightBumper",
"GroupName": "Inventory"
},
{
"Name": "View",
"KeyboardCode": "C",
"GamepadCode": "RightJoystickButton",
"GroupName": "Other"
},
{
"Name": "Voice",
"KeyboardCode": "v",
"GamepadCode": "None",
"GroupName": "Other"
},
{
"Name": "Drop",
"KeyboardCode": "g",
"GamepadCode": "None",
"GroupName": "Other"
},
{
"Name": "Flashlight",
"KeyboardCode": "f",
"GamepadCode": "DpadNorth",
"GroupName": "Other"
},
{
"Name": "Score",
"KeyboardCode": "tab",
"GamepadCode": "SwitchLeftMenu",
"GroupName": "Other"
},
{
"Name": "Menu",
"KeyboardCode": "Q",
"GamepadCode": "SwitchRightMenu",
"GroupName": "Other"
},
{
"Name": "Chat",
"KeyboardCode": "enter",
"GamepadCode": "None",
"GroupName": "Other"
}
],
"__guid": "2b0cbf43-3f45-425d-8560-9eaecf2ed2a3",
"__schema": "configdata",
"__type": "InputSettings",
"__version": 1
}

View File

@ -0,0 +1,41 @@
# Shrimple Character Controller
https://github.com/user-attachments/assets/374eea5b-7106-4c3e-8cb6-9bb56a1ff511
A shrimple yet versatile Character Controller/Move Helper that performs great.
Performs 60%-200% better than standard Character Controller.
You can find example scenes for the Walker, Roller, and Flyer here: [Controller Example Scenes](https://github.com/Small-Fish-Dev/shrimple_character_controller/tree/main/Assets/scenes)
Made from scratch using the classic [Collide and Slide](https://www.peroxide.dk/papers/collision/collision.pdf) method.
For any issues please report them here: [Github Issues](https://github.com/Small-Fish-Dev/shrimple_character_controller/issues)
# How to use
You can find code examples for the Walker, Roller, and Flyer here: [Example Controllers](https://github.com/Small-Fish-Dev/shrimple_character_controller/tree/main/code/Examples)
It all boils down to:
```
Controller.WishVelocity = Vector3.Forward;
Controller.Move();
```
You'll have to call `.Move()` only if your Controller options "Manual Update" is set to true. Otherwise you can set it to false and it will always be simulated.
You are also able to manually update the GameObject's transform rather than letting the Controller do it:
```
Controller.WishVelocity = wishDirection * wishSpeed;
var controllerResult = Controller.Move( false );
if ( controllerResult.Position.z <= 999f ) // Out of bounds!
{
Destroy();
}
else
{
Transform.Position = controllerResult.Position;
MyVelocity = controllerResult.Velocity;
}
```

View File

@ -0,0 +1,15 @@
{
"Title": "Shrimple Character Controller",
"Type": "library",
"Org": "fish",
"Ident": "scc",
"Schema": 1,
"IncludeSourceFiles": false,
"Resources": null,
"PackageReferences": [],
"EditorReferences": null,
"IsWhitelistDisabled": false,
"Metadata": {
"CsProjName": ""
}
}

View File

@ -0,0 +1,34 @@
{
"Defaults": {
"solid": "Collide",
"trigger": "Trigger",
"ladder": "Ignore",
"water": "Trigger"
},
"Pairs": [
{
"a": "solid",
"b": "solid",
"r": "Collide"
},
{
"a": "trigger",
"b": "playerclip",
"r": "Ignore"
},
{
"a": "trigger",
"b": "solid",
"r": "Trigger"
},
{
"a": "playerclip",
"b": "solid",
"r": "Collide"
}
],
"__guid": "c82378d5-1642-441e-91ec-098ea88ad35e",
"__schema": "configdata",
"__type": "CollisionRules",
"__version": 1
}

View File

@ -0,0 +1,194 @@
{
"Actions": [
{
"Name": "Forward",
"KeyboardCode": "W",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Backward",
"KeyboardCode": "S",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Left",
"KeyboardCode": "A",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Right",
"KeyboardCode": "D",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Jump",
"KeyboardCode": "space",
"GamepadCode": "A",
"GroupName": "Movement"
},
{
"Name": "Run",
"KeyboardCode": "shift",
"GamepadCode": "LeftJoystickButton",
"GroupName": "Movement"
},
{
"Name": "Walk",
"KeyboardCode": "alt",
"GamepadCode": "None",
"GroupName": "Movement"
},
{
"Name": "Duck",
"KeyboardCode": "ctrl",
"GamepadCode": "B",
"GroupName": "Movement"
},
{
"Name": "attack1",
"KeyboardCode": "mouse1",
"GamepadCode": "RightTrigger",
"GroupName": "Actions"
},
{
"Name": "attack2",
"KeyboardCode": "mouse2",
"GamepadCode": "LeftTrigger",
"GroupName": "Actions"
},
{
"Name": "reload",
"KeyboardCode": "r",
"GamepadCode": "X",
"GroupName": "Actions"
},
{
"Name": "use",
"KeyboardCode": "e",
"GamepadCode": "Y",
"GroupName": "Actions"
},
{
"Name": "Slot1",
"KeyboardCode": "1",
"GamepadCode": "DpadWest",
"GroupName": "Inventory"
},
{
"Name": "Slot2",
"KeyboardCode": "2",
"GamepadCode": "DpadEast",
"GroupName": "Inventory"
},
{
"Name": "Slot3",
"KeyboardCode": "3",
"GamepadCode": "DpadSouth",
"GroupName": "Inventory"
},
{
"Name": "Slot4",
"KeyboardCode": "4",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot5",
"KeyboardCode": "5",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot6",
"KeyboardCode": "6",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot7",
"KeyboardCode": "7",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot8",
"KeyboardCode": "8",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot9",
"KeyboardCode": "9",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "Slot0",
"KeyboardCode": "0",
"GamepadCode": "None",
"GroupName": "Inventory"
},
{
"Name": "SlotPrev",
"KeyboardCode": "mouse4",
"GamepadCode": "SwitchLeftBumper",
"GroupName": "Inventory"
},
{
"Name": "SlotNext",
"KeyboardCode": "mouse5",
"GamepadCode": "SwitchRightBumper",
"GroupName": "Inventory"
},
{
"Name": "View",
"KeyboardCode": "C",
"GamepadCode": "RightJoystickButton",
"GroupName": "Other"
},
{
"Name": "Voice",
"KeyboardCode": "v",
"GamepadCode": "None",
"GroupName": "Other"
},
{
"Name": "Drop",
"KeyboardCode": "g",
"GamepadCode": "None",
"GroupName": "Other"
},
{
"Name": "Flashlight",
"KeyboardCode": "f",
"GamepadCode": "DpadNorth",
"GroupName": "Other"
},
{
"Name": "Score",
"KeyboardCode": "tab",
"GamepadCode": "SwitchLeftMenu",
"GroupName": "Other"
},
{
"Name": "Menu",
"KeyboardCode": "Q",
"GamepadCode": "SwitchRightMenu",
"GroupName": "Other"
},
{
"Name": "Chat",
"KeyboardCode": "enter",
"GamepadCode": "None",
"GroupName": "Other"
}
],
"__guid": "0227f25a-537a-4f15-a72a-90f6af33742f",
"__schema": "configdata",
"__type": "InputSettings",
"__version": 1
}

29
kakozuzo_2.sbproj Normal file
View File

@ -0,0 +1,29 @@
{
"Title": "kakozuzo_2",
"Type": "game",
"Org": "koptilnya",
"Ident": "kakozuzo_2",
"Schema": 1,
"IncludeSourceFiles": false,
"Resources": null,
"PackageReferences": [],
"EditorReferences": null,
"IsWhitelistDisabled": false,
"Metadata": {
"MaxPlayers": 64,
"MinPlayers": 1,
"TickRate": 50,
"GameNetworkType": "Multiplayer",
"MapSelect": "Unrestricted",
"MapList": [
"facepunch.flatgrass"
],
"RankType": "None",
"PerMapRanking": false,
"LeaderboardType": "None",
"CsProjName": "",
"StartupScene": "scenes/minimal.scene",
"MapStartupScene": "scenes/minimal.scene",
"LaunchMode": "Normal"
}
}

View File

@ -0,0 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005Chamit_005Fba31xcg_005CDocuments_005Cs_0026box_0020projects_005Ckakozuzo_005F2_005CLibraries_005Cfish_002Escc_005Ccode_005CAssembly_002Ecs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005Chamit_005Fba31xcg_005CDocuments_005Cs_0026box_0020projects_005Ckakozuzo_005F2_005CLibraries_005Cfish_002Escc_005Cscc_002Esbproj/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>