This commit is contained in:
2026-06-04 21:26:19 +07:00
parent b61b79c82e
commit 45d3fe8c21
10 changed files with 400 additions and 33 deletions

View File

@@ -4,14 +4,18 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="f9183c68-daf0-43b8-be4c-fad79983f91b" name="Changes" comment="" />
<list default="true" id="f9183c68-daf0-43b8-be4c-fad79983f91b" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.HALLUCINATE/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Camera/vThirdPersonCamera.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Camera/vThirdPersonCamera.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Assets/Scripts/Camera/vThirdPersonCameraState.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Assets/Scripts/Camera/vThirdPersonCameraState.cs" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="EmbeddingIndexingInfo">
<option name="cachedIndexableFilesCount" value="80" />
<option name="cachedIndexableFilesCount" value="76" />
<option name="fileBasedEmbeddingIndicesEnabled" value="true" />
</component>
<component name="Git.Settings">
@@ -95,7 +99,7 @@
<option name="MIXED_MODE_DEBUG" value="0" />
<method v="2" />
</configuration>
<configuration name="Attach to Unity Editor" type="UNITY_DEBUG_RUN_CONFIGURATION" factoryName="Unity Debug" show_console_on_std_err="false" show_console_on_std_out="false" port="50000" address="localhost">
<configuration name="Attach to Unity Editor" type="UNITY_DEBUG_RUN_CONFIGURATION" factoryName="Unity Debug" show_console_on_std_err="false" show_console_on_std_out="false" port="50000" address="localhost" useMixedMode="false">
<option name="allowRunningInParallel" value="false" />
<option name="listenPortForConnections" value="false" />
<option name="pid" />
@@ -106,7 +110,6 @@
<option name="selectedOptions">
<list />
</option>
<option name="useMixedMode" value="false" />
<method v="2" />
</configuration>
<configuration name="Attach to" type="UnityDevicePlayer" factoryName="UnityAttachToDevicePlayer">
@@ -172,7 +175,6 @@
<workItem from="1780364354282" duration="4357000" />
<workItem from="1780409218377" duration="9852000" />
<workItem from="1780494322686" duration="643000" />
<workItem from="1780565492235" duration="309000" />
</task>
<servers />
</component>

75
Assets/InventoryData.json Normal file
View File

@@ -0,0 +1,75 @@
{
"itemReferences": [
{
"amount": 1,
"id": 10,
"attributes": [
{
"name": 2,
"value": 36,
"isOpen": false,
"isBool": false
},
{
"name": 6,
"value": 8,
"isOpen": false,
"isBool": false
}
]
}
],
"equipAreas": [
{
"slotsData": [
{
"hasItem": true,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
}
],
"indexOfSelectedSlot": 0
},
{
"slotsData": [
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
}
],
"indexOfSelectedSlot": 0
},
{
"slotsData": [
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
}
],
"indexOfSelectedSlot": 0
}
]
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 760274f8c30c80848a1fb1c5dc64a2d5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -3271,9 +3271,9 @@ GameObject:
- component: {fileID: 114525927984870190}
- component: {fileID: 832688648}
- component: {fileID: 6688537537024804213}
- component: {fileID: 1505227404007521061}
- component: {fileID: -3829962440237222997}
- component: {fileID: -3602722895466718484}
- component: {fileID: 1505227404007521061}
m_Layer: 8
m_Name: vShooterMelee_Inventory
m_TagString: Player
@@ -4686,6 +4686,20 @@ MonoBehaviour:
defaultDamageEffects:
- {fileID: 120346, guid: b8f2fe1ee1a01724cb72f5b0e6bd2eef, type: 3}
customDamageEffects: []
--- !u!114 &1505227404007521061
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 146720}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 16509f68a17b8004096bcf4acce328d6, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::PlayerInventory
treasuresCollected: 0
totalTreasuresNeeded: 3
--- !u!114 &-3829962440237222997
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -5065,20 +5079,6 @@ MonoBehaviour:
m_DefaultActionMap: Player
m_SplitScreenIndex: -1
m_Camera: {fileID: 0}
--- !u!114 &1505227404007521061
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 146720}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 16509f68a17b8004096bcf4acce328d6, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::PlayerInventory
treasuresCollected: 0
totalTreasuresNeeded: 3
--- !u!1 &149606
GameObject:
m_ObjectHideFlags: 0
@@ -7002,6 +7002,108 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
mainTarget: {fileID: 0}
inputReader: {fileID: -3829962440237222997}
fpvTarget: {fileID: 463090}
fpvFOV: 80
transitionDuration: 0.3
characterFading:
useCharacterFading: 1
minVisibleDistance: 1.2
fullyHiddenDistance: 0.6
characterRenderers: []
occlusionTransparency:
useTransparency: 1
transparencyLayers:
serializedVersion: 2
m_Bits: 0
fadeAlpha: 0.3
dynamicFOV:
useDynamicFOV: 1
tpvSprintFOV: 70
fpvSprintFOV: 95
fovSmoothTime: 5
shakeManager:
useShake: 1
shakeFrequency: 25
decayCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
enableFallImpactShake: 1
minFallHeightForShake: 2
maxFallHeightForShake: 10
minFallShakeIntensity: 0.5
maxFallShakeIntensity: 3
minFallShakeDuration: 0.2
maxFallShakeDuration: 0.8
fallHeightToIntensityCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 1
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: 1
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
fallHeightToDurationCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 1
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: 1
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
_smoothBetweenState: 6
_smoothCameraRotation: 12
_smoothSwitchSide: 2

View File

@@ -122,6 +122,8 @@ public class EnemyAI : MonoBehaviour
private NodeState ActionPatrol()
{
// Debug.Log("Patrolling...");
if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
agent.isStopped = false; // Đảm bảo NPC được phép di chuyển
agent.speed = moveSpeed * 0.5f; // Đi dạo nên đi chậm lại một chút
@@ -156,6 +158,8 @@ public class EnemyAI : MonoBehaviour
// Debug.Log("Chasing Player");
if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
agent.isStopped = false;
agent.speed = moveSpeed; // Phục hồi tốc độ rượt đuổi
agent.SetDestination(player.position);
@@ -169,6 +173,8 @@ public class EnemyAI : MonoBehaviour
// Debug.Log("Focus and Shoot!");
if (!agent.isActiveAndEnabled || !agent.isOnNavMesh) return NodeState.Failure;
// Dừng NavMeshAgent lại để đứng bắn, tránh bị trượt
agent.isStopped = true;

View File

@@ -1,6 +1,8 @@
using Invector.vCharacterController;
using Invector;
using Invector.vCharacterController;
using System.Collections;
using UnityEngine;
using OnlyScove.Scripts;
namespace Invector.vCamera
{
@@ -28,6 +30,19 @@ namespace Invector.vCamera
#region inspector properties
public Transform mainTarget;
public InputReader inputReader;
[Header("First Person View")]
public Transform fpvTarget;
[SerializeField] protected float fpvFOV = 80f;
[SerializeField] protected float transitionDuration = 0.3f;
[Header("Modular Features")]
[SerializeField] protected CameraCharacterFading characterFading = new CameraCharacterFading();
[SerializeField] protected CameraOcclusionTransparency occlusionTransparency = new CameraOcclusionTransparency();
[SerializeField] protected CameraDynamicFOV dynamicFOV = new CameraDynamicFOV();
[SerializeField] protected CameraShakeManager shakeManager = new CameraShakeManager();
[Tooltip("Lerp speed between Camera States")]
[SerializeField] protected float _smoothBetweenState = 6f;
public virtual float smoothBetweenState { get { return _smoothBetweenState; } set { _smoothBetweenState = value; } }
@@ -195,10 +210,56 @@ namespace Invector.vCamera
protected virtual void Start()
{
Init();
}
protected virtual void OnEnable()
{
if (inputReader != null)
{
inputReader.OnToggleViewEvent += ToggleCameraView;
inputReader.OnSwitchSideEvent += ToggleSwitchSide;
}
}
protected virtual void OnDisable()
{
if (inputReader != null)
{
inputReader.OnToggleViewEvent -= ToggleCameraView;
inputReader.OnSwitchSideEvent -= ToggleSwitchSide;
}
}
public virtual void ToggleSwitchSide()
{
SwitchRight(switchRight > 0);
}
public virtual void ToggleCameraView()
{
if (currentState.cameraMode == TPCameraMode.FirstPerson)
{
ChangeState("Default");
}
else
{
ChangeState("FirstPerson");
// If the state "FirstPerson" does not exist in the list,
// we force the mode to FirstPerson anyway
if (currentStateName != "FirstPerson")
{
currentState.cameraMode = TPCameraMode.FirstPerson;
currentStateName = "FirstPerson";
}
}
}
public virtual void TriggerFallImpactShake(float fallHeight)
{
shakeManager.TriggerFallImpactShake(fallHeight);
}
/// <summary>
/// Init camera.
/// </summary>
@@ -209,6 +270,9 @@ namespace Invector.vCamera
return;
}
if (inputReader == null) inputReader = mainTarget.GetComponent<InputReader>();
if (inputReader == null) inputReader = GameObject.FindObjectOfType<InputReader>();
firstUpdated = true;
useSmooth = true;
targetLookAt.rotation = startUsingTargetRotation ? mainTarget.rotation : transform.rotation;
@@ -256,6 +320,8 @@ namespace Invector.vCamera
currentTargetPos = new Vector3(currentTarget.position.x, currentTarget.position.y + offSetPlayerPivot, currentTarget.position.z) + currentTarget.transform.up * lerpState.height;
targetLookAt.position = currentTargetPos;
dynamicFOV.Initialize(currentState.fov, fpvFOV);
isInit = true;
}
@@ -292,7 +358,19 @@ namespace Invector.vCamera
case TPCameraMode.FixedPoint:
CameraFixed();
break;
case TPCameraMode.FirstPerson:
CameraMovement();
break;
}
// Modular Features
if (inputReader != null)
{
dynamicFOV.HandleDynamicFOV(targetCamera, inputReader,
currentState.cameraMode == TPCameraMode.FirstPerson ? CameraController.CameraViewMode.FirstPerson : CameraController.CameraViewMode.ThirdPerson);
}
shakeManager.HandleShake();
transform.position += shakeManager.ShakeOffset;
}
/// <summary>
@@ -799,6 +877,12 @@ namespace Invector.vCamera
currentState.CopyState(lerpState);
}
if (currentState.cameraMode == TPCameraMode.FirstPerson)
{
HandleFirstPersonMovement();
return;
}
if (currentState.useZoom)
{
currentZoom = Mathf.Clamp(currentZoom, currentState.minDistance, currentState.maxDistance);
@@ -918,9 +1002,44 @@ namespace Invector.vCamera
_euler.z = 0;
var _rot = Quaternion.Euler(_euler + currentState.rotationOffSet);
selfRigidbody.MoveRotation(Quaternion.Lerp(startRotation, _rot, transformWeight));
// Apply Fading and Transparency
characterFading.HandleCharacterFading(distance);
occlusionTransparency.HandleTransparency(transform, targetPos);
movementSpeed = Vector2.zero;
}
protected virtual void HandleFirstPersonMovement()
{
if (fpvTarget == null) return;
distance = 0;
targetCamera.fieldOfView = fpvFOV;
// Position
current_cPos = fpvTarget.position;
targetLookAt.position = current_cPos;
selfRigidbody.MovePosition(current_cPos);
// Rotation
float _mouseY = Mathf.LerpAngle(mouseYStart, mouseY, transformWeight);
float _mouseX = Mathf.LerpAngle(mouseXStart, mouseX, transformWeight);
Quaternion newRot = Quaternion.Euler(_mouseY + offsetMouse.y, _mouseX + offsetMouse.x, 0);
targetLookAt.rotation = useSmooth ? Quaternion.Lerp(targetLookAt.rotation, newRot, smoothCameraRotation * Time.fixedDeltaTime) : newRot;
selfRigidbody.MoveRotation(targetLookAt.rotation);
// Sync player body rotation (Yaw only)
if (mainTarget != null)
{
mainTarget.rotation = Quaternion.Euler(0, targetLookAt.eulerAngles.y, 0);
}
characterFading.HandleCharacterFading(0); // Fully hide character head if desired, or set to distance 0 for full hidden
occlusionTransparency.HandleTransparency(transform, fpvTarget.position);
}
protected virtual void CameraFixed()
{
if (useSmooth)

View File

@@ -1,8 +1,16 @@
using UnityEngine;
using UnityEngine;
using System.Collections.Generic;
namespace Invector
{
public enum TPCameraMode
{
FreeDirectional,
FixedAngle,
FixedPoint,
FirstPerson
}
[System.Serializable]
public class vThirdPersonCameraState
{
@@ -56,6 +64,60 @@ namespace Invector
fixedAngle = Vector2.zero;
cameraMode = TPCameraMode.FreeDirectional;
}
public void CopyState(vThirdPersonCameraState state)
{
this.Name = state.Name;
this.forward = state.forward;
this.right = state.right;
this.defaultDistance = state.defaultDistance;
this.maxDistance = state.maxDistance;
this.minDistance = state.minDistance;
this.height = state.height;
this.smooth = state.smooth;
this.smoothDamp = state.smoothDamp;
this.xMouseSensitivity = state.xMouseSensitivity;
this.yMouseSensitivity = state.yMouseSensitivity;
this.yMinLimit = state.yMinLimit;
this.yMaxLimit = state.yMaxLimit;
this.xMinLimit = state.xMinLimit;
this.xMaxLimit = state.xMaxLimit;
this.rotationOffSet = state.rotationOffSet;
this.cullingHeight = state.cullingHeight;
this.cullingMinDist = state.cullingMinDist;
this.fov = state.fov;
this.useZoom = state.useZoom;
this.fixedAngle = state.fixedAngle;
this.lookPoints = state.lookPoints;
this.cameraMode = state.cameraMode;
}
public void Slerp(vThirdPersonCameraState state, float t)
{
this.Name = state.Name;
this.forward = Mathf.Lerp(this.forward, state.forward, t);
this.right = Mathf.Lerp(this.right, state.right, t);
this.defaultDistance = Mathf.Lerp(this.defaultDistance, state.defaultDistance, t);
this.maxDistance = Mathf.Lerp(this.maxDistance, state.maxDistance, t);
this.minDistance = Mathf.Lerp(this.minDistance, state.minDistance, t);
this.height = Mathf.Lerp(this.height, state.height, t);
this.smooth = Mathf.Lerp(this.smooth, state.smooth, t);
this.smoothDamp = Mathf.Lerp(this.smoothDamp, state.smoothDamp, t);
this.xMouseSensitivity = Mathf.Lerp(this.xMouseSensitivity, state.xMouseSensitivity, t);
this.yMouseSensitivity = Mathf.Lerp(this.yMouseSensitivity, state.yMouseSensitivity, t);
this.yMinLimit = Mathf.Lerp(this.yMinLimit, state.yMinLimit, t);
this.yMaxLimit = Mathf.Lerp(this.yMaxLimit, state.yMaxLimit, t);
this.xMinLimit = Mathf.Lerp(this.xMinLimit, state.xMinLimit, t);
this.xMaxLimit = Mathf.Lerp(this.xMaxLimit, state.xMaxLimit, t);
this.rotationOffSet = Vector3.Lerp(this.rotationOffSet, state.rotationOffSet, t);
this.cullingHeight = Mathf.Lerp(this.cullingHeight, state.cullingHeight, t);
this.cullingMinDist = Mathf.Lerp(this.cullingMinDist, state.cullingMinDist, t);
this.fov = Mathf.Lerp(this.fov, state.fov, t);
this.useZoom = state.useZoom;
this.fixedAngle = Vector2.Lerp(this.fixedAngle, state.fixedAngle, t);
this.lookPoints = state.lookPoints;
this.cameraMode = state.cameraMode;
}
}
[System.Serializable]
@@ -66,11 +128,4 @@ namespace Invector
public Vector3 eulerAngle;
public bool freeRotation;
}
public enum TPCameraMode
{
FreeDirectional,
FixedAngle,
FixedPoint
}
}

View File

@@ -32,13 +32,13 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 1ba5636bfdd687347966f548dbf5a0bc, type: 3}
m_Texture: {fileID: 2800000, guid: db48e0e5caa2999469a4f3aa249c188b, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats: []
m_Colors:
- _Color: {r: 8, g: 0, b: 0, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _Vector0: {r: 1, g: 1, b: 0, a: 0}
m_BuildTextureStacks: []
m_AllowLocking: 1

View File

@@ -635,7 +635,7 @@
{
"name": "",
"id": "f365517f-5a04-4d18-afa0-369ab80e0c54",
"path": "<Keyboard>/f2",
"path": "<Keyboard>/f1",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",

View File

@@ -30,6 +30,7 @@ TagManager:
- CoverPoint
- Interactable
- AIAction
- Check
layers:
- Default
- TransparentFX