GodDamage_______Input Player Ofline -> Online

This commit is contained in:
emDuy
2026-06-26 03:09:06 +07:00
parent 89763fda5e
commit 8dd33f0ae4
7 changed files with 297 additions and 50 deletions

View File

@@ -10,7 +10,15 @@
<configurations />
</component>
<component name="ChangeListManager">
<list default="true" id="d308d1cb-09fc-4331-ba20-00f7b43d1576" name="Changes" comment="" />
<list default="true" id="d308d1cb-09fc-4331-ba20-00f7b43d1576" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.BABA_YAGA/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.BABA_YAGA/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Network/BasicSpawner.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Network/BasicSpawner.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Network/FusionClientMovementBridge.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Network/FusionClientMovementBridge.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Network/PlayerInputData.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Network/PlayerInputData.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Third Parties/Opsive/UltimateCharacterController/Demo/Demo.unity" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Third Parties/Opsive/UltimateCharacterController/Demo/Demo.unity" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Third Parties/Opsive/UltimateCharacterController/Demo/Materials/Items/Shooter/AssaultRifle/MuzzleFlash.mat" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Third Parties/Opsive/UltimateCharacterController/Demo/Materials/Items/Shooter/AssaultRifle/MuzzleFlash.mat" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Third Parties/Opsive/UltimateCharacterController/Scripts/Character/UltimateCharacterLocomotion.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Third Parties/Opsive/UltimateCharacterController/Scripts/Character/UltimateCharacterLocomotion.cs" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -18,7 +26,6 @@
</component>
<component name="EmbeddingIndexingInfo">
<option name="cachedIndexableFilesCount" value="13" />
<option name="fileBasedEmbeddingIndicesEnabled" value="true" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
@@ -37,6 +44,65 @@
<commands />
<urls />
</component>
<component name="NextEditCompletionFeaturesState">
<decayedCancelled>
<entry key="MS100" value="0.0" />
<entry key="MS500" value="0.0" />
<entry key="S2" value="3.8675E-320" />
<entry key="S5" value="3.319571197732691E-128" />
<entry key="S10" value="3.1555398328979666E-64" />
<entry key="S30" value="1.4181654461189165E-21" />
<entry key="S60" value="6.720324789873212E-11" />
<entry key="M2" value="1.599542645376073E-5" />
<entry key="M5" value="0.030087570117273955" />
<entry key="M10" value="0.3838671981899085" />
<entry key="M15" value="0.9010164877261028" />
<entry key="M30" value="2.1199193906946707" />
<entry key="H1" value="3.254692904249998" />
<entry key="H2" value="4.033723779233439" />
<entry key="H4" value="4.49086079416214" />
<entry key="D1" value="4.911288223926045" />
<entry key="W1" value="4.987229120187288" />
</decayedCancelled>
<decayedSelected>
<entry key="MS100" value="1.0" />
<entry key="MS500" value="1.0000000000975013" />
<entry key="S2" value="1.0034885658070831" />
<entry key="S5" value="1.141031907863601" />
<entry key="S10" value="1.5190154111141159" />
<entry key="S30" value="2.268899319587759" />
<entry key="S60" value="2.5919730257668347" />
<entry key="M2" value="2.7840603648137137" />
<entry key="M5" value="2.9105755544220724" />
<entry key="M10" value="2.9547632826955033" />
<entry key="M15" value="2.9697243871367087" />
<entry key="M30" value="2.984802977961377" />
<entry key="H1" value="2.9923866257246665" />
<entry key="H2" value="2.9961895896024644" />
<entry key="H4" value="2.9980938630538656" />
<entry key="D1" value="2.999682181020405" />
<entry key="W1" value="2.9999545941164474" />
</decayedSelected>
<decayedShown>
<entry key="MS100" value="1.4412822141706837E-9" />
<entry key="MS500" value="0.01705099807902734" />
<entry key="S2" value="0.3618205240431099" />
<entry key="S5" value="0.7191340629999607" />
<entry key="S10" value="1.1168459715817314" />
<entry key="S30" value="1.9750373527326854" />
<entry key="S60" value="2.405160093575036" />
<entry key="M2" value="2.678152016044813" />
<entry key="M5" value="2.8948856234368048" />
<entry key="M10" value="3.315083250745922" />
<entry key="M15" value="3.854849910859975" />
<entry key="M30" value="5.096640322333532" />
<entry key="H1" value="6.242989225916026" />
<entry key="H2" value="7.027852823712892" />
<entry key="H4" value="7.487920043243343" />
<entry key="D1" value="7.910797318195639" />
<entry key="W1" value="7.9871589710056945" />
</decayedShown>
</component>
<component name="ProblemsViewState">
<option name="selectedTabId" value="CurrentFile" />
</component>
@@ -48,34 +114,34 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ModuleVcsDetector.initialDetectionPerformed": "true",
"RunOnceActivity.MCP Project settings loaded": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
"RunOnceActivity.cidr.known.project.marker": "true",
"RunOnceActivity.git.unshallow": "true",
"RunOnceActivity.readMode.enableVisualFormatting": "true",
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
"cidr.known.project.marker": "true",
"codeWithMe.voiceChat.enabledByDefault": "false",
"com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
"git-widget-placeholder": "main",
"junie.onboarding.icon.badge.shown": "true",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.lookFeel",
"to.speed.mode.migration.done": "true",
"vue.rearranger.settings.migration": "true"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;,
&quot;RunOnceActivity.MCP Project settings loaded&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;,
&quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;RunOnceActivity.readMode.enableVisualFormatting&quot;: &quot;true&quot;,
&quot;RunOnceActivity.typescript.service.memoryLimit.init&quot;: &quot;true&quot;,
&quot;cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;codeWithMe.voiceChat.enabledByDefault&quot;: &quot;false&quot;,
&quot;com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;junie.onboarding.icon.badge.shown&quot;: &quot;true&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.lookFeel&quot;,
&quot;to.speed.mode.migration.done&quot;: &quot;true&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}]]></component>
}</component>
<component name="RunManager" selected="Attach to Unity Editor.Attach to Unity Editor">
<configuration name="Start Unity" type="RunUnityExe" factoryName="Unity Executable">
<option name="EXE_PATH" value="C:\Program Files\Unity\Hub\Editor\6000.3.10f1\Editor\Unity.exe" />
<option name="EXE_PATH" value="E:\APPDATA\6000.3.10f1\Editor\Unity.exe" />
<option name="PROGRAM_PARAMETERS" value="-projectPath D:\Learning_Progress\Projects\BABA_YAGA -debugCodeOptimization" />
<option name="WORKING_DIRECTORY" value="D:\Learning_Progress\Projects\BABA_YAGA" />
<option name="PASS_PARENT_ENVS" value="1" />
@@ -85,7 +151,7 @@
<method v="2" />
</configuration>
<configuration name="Unit Tests (batch mode)" type="RunUnityExe" factoryName="Unity Executable">
<option name="EXE_PATH" value="C:\Program Files\Unity\Hub\Editor\6000.3.10f1\Editor\Unity.exe" />
<option name="EXE_PATH" value="E:\APPDATA\6000.3.10f1\Editor\Unity.exe" />
<option name="PROGRAM_PARAMETERS" value="-runTests -batchmode -projectPath D:\Learning_Progress\Projects\BABA_YAGA -testResults Logs/results.xml -logFile Logs/Editor.log -testPlatform EditMode -debugCodeOptimization" />
<option name="WORKING_DIRECTORY" value="D:\Learning_Progress\Projects\BABA_YAGA" />
<option name="PASS_PARENT_ENVS" value="1" />
@@ -130,6 +196,7 @@
<workItem from="1781765548760" duration="8210000" />
<workItem from="1782307099768" duration="1913000" />
<workItem from="1782350909857" duration="4496000" />
<workItem from="1782411917571" duration="2647000" />
</task>
<servers />
</component>

View File

@@ -350,16 +350,12 @@ namespace Hallucinate.UI
public void OnInput(NetworkRunner runner, NetworkInput input)
{
// var data = new PlayerInputData();
// if (PlayerStateMachine.Local != null && PlayerStateMachine.Local.Input != null)
// {
// data.Direction = PlayerStateMachine.Local.Input.MoveInput;
// data.sprint = PlayerStateMachine.Local.Input.IsSprintHeld;
// data.jump = PlayerStateMachine.Local.Input.ConsumeJumpInput();
// if (PlayerStateMachine.Local.Cam != null)
// data.rot = PlayerStateMachine.Local.Cam.PlanarRotation;
// }
// input.Set(data);
var data = new PlayerInputData();
if (Hallucinate.Network.FusionClientMovementBridge.Local != null)
{
data = Hallucinate.Network.FusionClientMovementBridge.Local.GetLocalInputData();
}
input.Set(data);
}
public void OnConnectedToServer(NetworkRunner runner) { }

View File

@@ -1,26 +1,50 @@
using UnityEngine;
using Fusion;
using Opsive.Shared.Events;
using Opsive.UltimateCharacterController.Networking;
using Opsive.UltimateCharacterController.Networking.Character;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Camera; // Corrected namespace
using Opsive.UltimateCharacterController.Input; // Corrected namespace
using Opsive.UltimateCharacterController.Character.Abilities;
using Opsive.UltimateCharacterController.Character.Abilities.Items;
using Opsive.UltimateCharacterController.Camera;
using Opsive.UltimateCharacterController.Input;
using OnlyScove.Scripts;
using Opsive.UltimateCharacterController.Game;
namespace Hallucinate.Network
{
// Ensure Opsive components load before this
[DefaultExecutionOrder(100)]
public class FusionClientMovementBridge : NetworkBehaviour, INetworkInfo, INetworkCharacter
public class FusionClientMovementBridge : NetworkBehaviour, INetworkInfo, INetworkCharacter, ILookSource
{
public static FusionClientMovementBridge Local { get; private set; }
[Networked]
public PlayerInputData SyncInput { get; set; }
private UltimateCharacterLocomotion m_CharacterLocomotion;
private UltimateCharacterLocomotionHandler m_LocoHandler;
private Opsive.UltimateCharacterController.Input.PlayerInput m_PlayerInput;
private void Awake()
{
m_CharacterLocomotion = GetComponent<UltimateCharacterLocomotion>();
m_LocoHandler = GetComponent<UltimateCharacterLocomotionHandler>();
m_PlayerInput = GetComponent<Opsive.UltimateCharacterController.Input.PlayerInput>();
}
public override void Spawned()
{
// Because we passed State Authority to the client in BasicSpawner,
// HasStateAuthority is true ONLY for the local player.
bool isLocal = Object.HasStateAuthority;
if (isLocal)
{
Local = this;
}
// 1. Isolate Input: Only the local player should read keyboard/mouse inputs.
var locoHandler = GetComponent<UltimateCharacterLocomotionHandler>();
if (locoHandler != null) locoHandler.enabled = isLocal;
if (m_LocoHandler != null) m_LocoHandler.enabled = isLocal;
var activeInput = GetComponent<UnityInput>(); // Corrected class reference
if (activeInput != null) activeInput.enabled = isLocal;
@@ -34,6 +58,150 @@ namespace Hallucinate.Network
cameraController.Character = gameObject;
}
}
else
{
// For remote players, register this bridge as the LookSource
EventHandler.ExecuteEvent<ILookSource>(gameObject, "OnCharacterAttachLookSource", this);
}
}
public override void Despawned(NetworkRunner runner, bool hasState)
{
if (Local == this)
{
Local = null;
}
}
public override void FixedUpdateNetwork()
{
if (Object.HasStateAuthority)
{
if (GetInput<PlayerInputData>(out var input))
{
SyncInput = input;
}
}
if (!Object.HasStateAuthority)
{
// Ensure look source is attached for remote players
if (m_CharacterLocomotion != null && m_CharacterLocomotion.LookSource != (ILookSource)this)
{
EventHandler.ExecuteEvent<ILookSource>(gameObject, "OnCharacterAttachLookSource", this);
}
// Sync the movement inputs to KinematicObjectManager so it moves the remote player character
if (m_CharacterLocomotion != null && m_CharacterLocomotion.KinematicObjectIndex != -1)
{
KinematicObjectManager.SetCharacterMovementInput(
m_CharacterLocomotion.KinematicObjectIndex,
SyncInput.Direction.x,
SyncInput.Direction.y
);
}
if (m_CharacterLocomotion != null)
{
m_CharacterLocomotion.InputVector = SyncInput.InputVector;
m_CharacterLocomotion.RawInputVector = SyncInput.RawInputVector;
m_CharacterLocomotion.DeltaRotation = SyncInput.DeltaRotation;
// Sync remote abilities based on state
UpdateRemoteAbility<SpeedChange>(SyncInput.sprint);
UpdateRemoteAbility<Jump>(SyncInput.jump);
UpdateRemoteAbility<HeightChange>(SyncInput.crouch);
UpdateRemoteAbility<Aim>(SyncInput.aim);
UpdateRemoteAbility<Use>(SyncInput.use);
UpdateRemoteAbility<Reload>(SyncInput.reload);
}
}
}
private void UpdateRemoteAbility<T>(bool shouldBeActive) where T : Ability
{
if (m_CharacterLocomotion == null) return;
var ability = m_CharacterLocomotion.GetAbility<T>();
if (ability != null)
{
if (shouldBeActive && !ability.IsActive)
{
m_CharacterLocomotion.TryStartAbility(ability, true);
}
else if (!shouldBeActive && ability.IsActive)
{
m_CharacterLocomotion.TryStopAbility(ability, true);
}
}
}
public PlayerInputData GetLocalInputData()
{
var data = new PlayerInputData();
if (m_CharacterLocomotion == null) return data;
if (m_PlayerInput != null)
{
data.Direction = new Vector2(m_PlayerInput.GetAxisRaw("Horizontal"), m_PlayerInput.GetAxisRaw("Vertical"));
// Sync abilities active states or buttons
data.sprint = IsAbilityActive<SpeedChange>() || m_PlayerInput.GetButton("Change Speeds");
data.jump = IsAbilityActive<Jump>() || m_PlayerInput.GetButton("Jump");
data.crouch = IsAbilityActive<HeightChange>() || m_PlayerInput.GetButton("Crouch");
data.aim = IsAbilityActive<Aim>() || m_PlayerInput.GetButton("Aim");
data.use = IsAbilityActive<Use>() || m_PlayerInput.GetButton("Fire1");
data.reload = IsAbilityActive<Reload>() || m_PlayerInput.GetButton("Reload");
}
// Sync locomotion internal state parameters
data.InputVector = m_CharacterLocomotion.InputVector;
data.RawInputVector = m_CharacterLocomotion.RawInputVector;
data.DeltaRotation = m_CharacterLocomotion.DeltaRotation;
data.rot = transform.rotation;
// Sync Look direction and look pitch
var lookSource = m_CharacterLocomotion.LookSource;
if (lookSource != null)
{
data.LookPitch = lookSource.Pitch;
data.LookDirection = lookSource.LookDirection(true);
}
return data;
}
private bool IsAbilityActive<T>() where T : Ability
{
if (m_CharacterLocomotion == null) return false;
var ability = m_CharacterLocomotion.GetAbility<T>();
return ability != null && ability.IsActive;
}
// --- ILookSource Implementation ---
public GameObject GameObject => gameObject;
public Transform Transform => transform;
public float LookDirectionDistance => 1f;
public float Pitch => SyncInput.LookPitch;
public Vector3 LookPosition()
{
var animator = GetComponent<Animator>();
if (animator != null)
{
var head = animator.GetBoneTransform(HumanBodyBones.Head);
if (head != null) return head.position;
}
return transform.position + Vector3.up * 1.5f;
}
public Vector3 LookDirection(bool characterLookDirection)
{
return SyncInput.LookDirection == Vector3.zero ? transform.forward : SyncInput.LookDirection;
}
public Vector3 LookDirection(Vector3 lookPosition, bool characterLookDirection, int layerMask, bool useRecoil)
{
return LookDirection(characterLookDirection);
}
// --- INetworkInfo Implementation ---
@@ -56,13 +224,11 @@ namespace Hallucinate.Network
public void ResetRotationPosition() { }
public void SetActive(bool active, bool uiEvent) { }
// Optional interface stubs for weapons/items (leave empty for now to focus on movement)
public void LoadDefaultLoadout() { }
public void EquipUnequipItem(uint itemID, int slotID, bool equip) { }
public void ItemIdentifierPickup(uint id, int amount, int slot, bool immediate, bool force) { }
public void RemoveAllItems() { }
// New missing interface stubs for Shooter/Melee compiled code
public void Fire(Opsive.UltimateCharacterController.Items.Actions.ItemAction itemAction, float strength) { }
public void StartItemReload(Opsive.UltimateCharacterController.Items.Actions.ItemAction itemAction) { }
public void ReloadItem(Opsive.UltimateCharacterController.Items.Actions.ItemAction itemAction, bool fullClip) { }

View File

@@ -4,7 +4,7 @@ using UnityEngine;
namespace OnlyScove.Scripts
{
public struct PlayerInputData : INetworkInput
public struct PlayerInputData : INetworkInput, INetworkStruct
{
// Di chuyển (thường là Vector2 cho X/Y hoặc WASD)
public Vector2 Direction;

View File

@@ -115890,7 +115890,7 @@ PrefabInstance:
m_SourcePrefab: {fileID: 100100000, guid: ffa7be873c1b8bb449949137ae680ba6, type: 3}
--- !u!4 &1254910863 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 4737921192513690, guid: ffa7be873c1b8bb449949137ae680ba6, type: 3}
m_CorrespondingSourceObject: {fileID: 9223372036854775806, guid: ffa7be873c1b8bb449949137ae680ba6, type: 3}
m_PrefabInstance: {fileID: 1254910862}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &1255434433

View File

@@ -81,6 +81,6 @@ Material:
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _TintColor: {r: 1, g: 1, b: 1, a: 0}
- _TintColor: {r: 0, g: 0, b: 0, a: 0}
m_BuildTextureStacks: []
m_AllowLocking: 1

View File

@@ -1,4 +1,4 @@
/// ---------------------------------------------
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
@@ -928,6 +928,15 @@ namespace Opsive.UltimateCharacterController.Character
}
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo != null && !m_NetworkInfo.IsLocalPlayer()) {
m_Up = m_Transform.up;
m_MotorRotation = m_Transform.rotation;
m_Torque = Quaternion.identity;
return;
}
#endif
base.ApplyRotation();
}
@@ -989,6 +998,15 @@ namespace Opsive.UltimateCharacterController.Character
m_ActiveItemAbilities[i].ApplyPosition();
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
if (m_NetworkInfo != null && !m_NetworkInfo.IsLocalPlayer()) {
m_Velocity = (m_Transform.position - m_PrevPosition) / (m_TimeScale * Time.deltaTime);
m_PrevPosition = m_Transform.position;
m_MoveDirection = Vector3.zero;
return;
}
#endif
base.ApplyPosition();
}