Merge pull request 'rewrite_interactables' (#2) from rewrite_interactables into main
Reviewed-on: #2
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
using UnityEditor;
|
using Interactions;
|
||||||
|
using PuzzleS;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Editor
|
namespace Editor
|
||||||
@@ -13,6 +15,9 @@ namespace Editor
|
|||||||
private string _pickupSoFolderPath = "Assets/Data/Items";
|
private string _pickupSoFolderPath = "Assets/Data/Items";
|
||||||
private string _puzzleSoFolderPath = "Assets/Data/Puzzles";
|
private string _puzzleSoFolderPath = "Assets/Data/Puzzles";
|
||||||
|
|
||||||
|
private enum ItemType { None, Pickup, ItemSlot }
|
||||||
|
private ItemType _itemType = ItemType.None;
|
||||||
|
|
||||||
[MenuItem("Tools/Item Prefab Editor")]
|
[MenuItem("Tools/Item Prefab Editor")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
@@ -53,39 +58,28 @@ namespace Editor
|
|||||||
|
|
||||||
EditorGUILayout.LabelField("Editing: ", _selectedGameObject.name, EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Editing: ", _selectedGameObject.name, EditorStyles.boldLabel);
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
// Pickup
|
|
||||||
|
// Determine current type
|
||||||
bool hasPickup = _selectedGameObject.GetComponent<Pickup>() != null;
|
bool hasPickup = _selectedGameObject.GetComponent<Pickup>() != null;
|
||||||
bool addPickup = EditorGUILayout.Toggle("Pickup", hasPickup);
|
bool hasSlot = _selectedGameObject.GetComponent<ItemSlot>() != null;
|
||||||
if (addPickup && !hasPickup)
|
if (hasSlot) _itemType = ItemType.ItemSlot;
|
||||||
{
|
else if (hasPickup) _itemType = ItemType.Pickup;
|
||||||
PrefabEditorUtility.AddOrGetComponent<Pickup>(_selectedGameObject);
|
else _itemType = ItemType.None;
|
||||||
}
|
|
||||||
else if (!addPickup && hasPickup)
|
// Item type selection
|
||||||
|
var newType = (ItemType)EditorGUILayout.EnumPopup("Item Type", _itemType);
|
||||||
|
if (newType != _itemType)
|
||||||
{
|
{
|
||||||
|
// Remove both, then add selected
|
||||||
PrefabEditorUtility.RemoveComponent<Pickup>(_selectedGameObject);
|
PrefabEditorUtility.RemoveComponent<Pickup>(_selectedGameObject);
|
||||||
|
PrefabEditorUtility.RemoveComponent<ItemSlot>(_selectedGameObject);
|
||||||
|
if (newType == ItemType.Pickup)
|
||||||
|
PrefabEditorUtility.AddOrGetComponent<Pickup>(_selectedGameObject);
|
||||||
|
else if (newType == ItemType.ItemSlot)
|
||||||
|
PrefabEditorUtility.AddOrGetComponent<ItemSlot>(_selectedGameObject);
|
||||||
|
_itemType = newType;
|
||||||
}
|
}
|
||||||
// CombineWithBehavior
|
|
||||||
bool hasCombine = _selectedGameObject.GetComponent<CombineWithBehavior>() != null;
|
|
||||||
bool addCombine = EditorGUILayout.Toggle("CombineWithBehavior", hasCombine);
|
|
||||||
if (addCombine && !hasCombine)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.AddOrGetComponent<CombineWithBehavior>(_selectedGameObject);
|
|
||||||
}
|
|
||||||
else if (!addCombine && hasCombine)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.RemoveComponent<CombineWithBehavior>(_selectedGameObject);
|
|
||||||
}
|
|
||||||
// SlotItemBehavior
|
|
||||||
bool hasSlot = _selectedGameObject.GetComponent<SlotItemBehavior>() != null;
|
|
||||||
bool addSlot = EditorGUILayout.Toggle("SlotItemBehavior", hasSlot);
|
|
||||||
if (addSlot && !hasSlot)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.AddOrGetComponent<SlotItemBehavior>(_selectedGameObject);
|
|
||||||
}
|
|
||||||
else if (!addSlot && hasSlot)
|
|
||||||
{
|
|
||||||
PrefabEditorUtility.RemoveComponent<SlotItemBehavior>(_selectedGameObject);
|
|
||||||
}
|
|
||||||
// ObjectiveStepBehaviour
|
// ObjectiveStepBehaviour
|
||||||
bool hasObjective = _selectedGameObject.GetComponent<ObjectiveStepBehaviour>() != null;
|
bool hasObjective = _selectedGameObject.GetComponent<ObjectiveStepBehaviour>() != null;
|
||||||
bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", hasObjective);
|
bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", hasObjective);
|
||||||
@@ -97,8 +91,9 @@ namespace Editor
|
|||||||
{
|
{
|
||||||
PrefabEditorUtility.RemoveComponent<ObjectiveStepBehaviour>(_selectedGameObject);
|
PrefabEditorUtility.RemoveComponent<ObjectiveStepBehaviour>(_selectedGameObject);
|
||||||
}
|
}
|
||||||
// Pickup Data
|
|
||||||
if (addPickup)
|
// Pickup Data (for Pickup or ItemSlot)
|
||||||
|
if (_itemType == ItemType.Pickup || _itemType == ItemType.ItemSlot)
|
||||||
{
|
{
|
||||||
var pickup = _selectedGameObject.GetComponent<Pickup>();
|
var pickup = _selectedGameObject.GetComponent<Pickup>();
|
||||||
_pickupData = pickup.itemData;
|
_pickupData = pickup.itemData;
|
||||||
@@ -122,6 +117,7 @@ namespace Editor
|
|||||||
pickup.itemData = _pickupData;
|
pickup.itemData = _pickupData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Objective Data
|
// Objective Data
|
||||||
if (addObjective)
|
if (addObjective)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Interactions;
|
||||||
|
using PuzzleS;
|
||||||
|
|
||||||
namespace Editor
|
namespace Editor
|
||||||
{
|
{
|
||||||
@@ -10,15 +12,17 @@ namespace Editor
|
|||||||
private string _saveFolderPath = "Assets/Prefabs/Items";
|
private string _saveFolderPath = "Assets/Prefabs/Items";
|
||||||
private string _pickupSoFolderPath = "Assets/Data/Items";
|
private string _pickupSoFolderPath = "Assets/Data/Items";
|
||||||
private string _puzzleSoFolderPath = "Assets/Data/Puzzles";
|
private string _puzzleSoFolderPath = "Assets/Data/Puzzles";
|
||||||
private bool _addPickup;
|
|
||||||
private bool _addCombineWith;
|
|
||||||
private bool _addSlot;
|
|
||||||
private bool _addObjective;
|
private bool _addObjective;
|
||||||
|
|
||||||
private PickupItemData _pickupData;
|
private PickupItemData _pickupData;
|
||||||
private PuzzleStepSO _objectiveData;
|
private PuzzleStepSO _objectiveData;
|
||||||
private UnityEditor.Editor _soEditor;
|
private UnityEditor.Editor _soEditor;
|
||||||
|
|
||||||
|
private enum ItemType { None, Pickup, ItemSlot }
|
||||||
|
private ItemType _itemType = ItemType.None;
|
||||||
|
|
||||||
|
private bool _createNext = false;
|
||||||
|
|
||||||
[MenuItem("Tools/Prefab Creator")]
|
[MenuItem("Tools/Prefab Creator")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
@@ -48,13 +52,19 @@ namespace Editor
|
|||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
EditorGUILayout.LabelField("Add Components:", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Add Components:", EditorStyles.boldLabel);
|
||||||
_addPickup = EditorGUILayout.Toggle("Pickup", _addPickup);
|
|
||||||
_addCombineWith = EditorGUILayout.Toggle("CombineWithBehavior", _addCombineWith);
|
// Item type selection
|
||||||
_addSlot = EditorGUILayout.Toggle("SlotItemBehavior", _addSlot);
|
var newType = (ItemType)EditorGUILayout.EnumPopup("Item Type", _itemType);
|
||||||
_addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", _addObjective);
|
if (newType != _itemType)
|
||||||
|
{
|
||||||
|
_itemType = newType;
|
||||||
|
}
|
||||||
|
bool addObjective = EditorGUILayout.Toggle("ObjectiveStepBehaviour", _addObjective);
|
||||||
|
_addObjective = addObjective;
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
if (_addPickup)
|
// Pickup Data (for Pickup or ItemSlot)
|
||||||
|
if (_itemType == ItemType.Pickup || _itemType == ItemType.ItemSlot)
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField("Pickup Data:", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Pickup Data:", EditorStyles.boldLabel);
|
||||||
_pickupData = (PickupItemData)EditorGUILayout.ObjectField("PickupItemData", _pickupData, typeof(PickupItemData), false);
|
_pickupData = (PickupItemData)EditorGUILayout.ObjectField("PickupItemData", _pickupData, typeof(PickupItemData), false);
|
||||||
@@ -76,6 +86,7 @@ namespace Editor
|
|||||||
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData);
|
PrefabEditorUtility.DrawScriptableObjectEditor(ref _soEditor, _pickupData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Objective Data
|
||||||
if (_addObjective)
|
if (_addObjective)
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField("Objective Data:", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Objective Data:", EditorStyles.boldLabel);
|
||||||
@@ -99,12 +110,15 @@ namespace Editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
GUILayout.FlexibleSpace();
|
GUILayout.FlexibleSpace();
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
GUI.enabled = !string.IsNullOrEmpty(_prefabName) && !string.IsNullOrEmpty(_saveFolderPath);
|
GUI.enabled = !string.IsNullOrEmpty(_prefabName) && !string.IsNullOrEmpty(_saveFolderPath);
|
||||||
if (GUILayout.Button("Create Prefab"))
|
if (GUILayout.Button("Create Prefab", GUILayout.Height(28)))
|
||||||
{
|
{
|
||||||
CreatePrefab();
|
CreatePrefab();
|
||||||
}
|
}
|
||||||
|
_createNext = GUILayout.Toggle(_createNext, "Create Next", GUILayout.Width(100), GUILayout.Height(28));
|
||||||
GUI.enabled = true;
|
GUI.enabled = true;
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreatePrefab()
|
private void CreatePrefab()
|
||||||
@@ -116,18 +130,15 @@ namespace Editor
|
|||||||
if (interactableLayer != -1)
|
if (interactableLayer != -1)
|
||||||
go.layer = interactableLayer;
|
go.layer = interactableLayer;
|
||||||
go.AddComponent<SpriteRenderer>();
|
go.AddComponent<SpriteRenderer>();
|
||||||
if (_addPickup)
|
if (_itemType == ItemType.Pickup)
|
||||||
{
|
{
|
||||||
var pickup = go.AddComponent<Pickup>();
|
var pickup = go.AddComponent<Pickup>();
|
||||||
pickup.itemData = _pickupData;
|
pickup.itemData = _pickupData;
|
||||||
}
|
}
|
||||||
if (_addCombineWith)
|
else if (_itemType == ItemType.ItemSlot)
|
||||||
{
|
{
|
||||||
go.AddComponent<CombineWithBehavior>();
|
var slot = go.AddComponent<ItemSlot>();
|
||||||
}
|
slot.itemData = _pickupData;
|
||||||
if (_addSlot)
|
|
||||||
{
|
|
||||||
go.AddComponent<SlotItemBehavior>();
|
|
||||||
}
|
}
|
||||||
if (_addObjective)
|
if (_addObjective)
|
||||||
{
|
{
|
||||||
@@ -135,10 +146,23 @@ namespace Editor
|
|||||||
obj.stepData = _objectiveData;
|
obj.stepData = _objectiveData;
|
||||||
}
|
}
|
||||||
string prefabPath = Path.Combine(_saveFolderPath, _prefabName + ".prefab").Replace("\\", "/");
|
string prefabPath = Path.Combine(_saveFolderPath, _prefabName + ".prefab").Replace("\\", "/");
|
||||||
PrefabUtility.SaveAsPrefabAsset(go, prefabPath);
|
var prefab = PrefabUtility.SaveAsPrefabAsset(go, prefabPath);
|
||||||
DestroyImmediate(go);
|
DestroyImmediate(go);
|
||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
|
Selection.activeObject = prefab;
|
||||||
|
EditorGUIUtility.PingObject(prefab);
|
||||||
EditorUtility.DisplayDialog("Prefab Created", $"Prefab saved to {prefabPath}", "OK");
|
EditorUtility.DisplayDialog("Prefab Created", $"Prefab saved to {prefabPath}", "OK");
|
||||||
|
if (_createNext)
|
||||||
|
{
|
||||||
|
_prefabName = "NewPrefab";
|
||||||
|
_pickupData = null;
|
||||||
|
_objectiveData = null;
|
||||||
|
_itemType = ItemType.None;
|
||||||
|
_addObjective = false;
|
||||||
|
_soEditor = null;
|
||||||
|
GUI.FocusControl(null);
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ using UnityEngine;
|
|||||||
using UnityEditor.SceneManagement;
|
using UnityEditor.SceneManagement;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Interactions;
|
||||||
|
using PuzzleS;
|
||||||
|
|
||||||
public class SceneObjectLocatorWindow : EditorWindow
|
public class SceneObjectLocatorWindow : EditorWindow
|
||||||
{
|
{
|
||||||
@@ -43,12 +45,10 @@ public class SceneObjectLocatorWindow : EditorWindow
|
|||||||
foreach (var pickup in pickups)
|
foreach (var pickup in pickups)
|
||||||
{
|
{
|
||||||
var go = pickup.gameObject;
|
var go = pickup.gameObject;
|
||||||
bool hasCombine = go.GetComponent<CombineWithBehavior>() != null;
|
bool hasSlot = go.GetComponent<ItemSlot>() != null;
|
||||||
bool hasSlot = go.GetComponent<SlotItemBehavior>() != null;
|
|
||||||
pickupInfos.Add(new PickupInfo
|
pickupInfos.Add(new PickupInfo
|
||||||
{
|
{
|
||||||
pickup = pickup,
|
pickup = pickup,
|
||||||
hasCombine = hasCombine,
|
|
||||||
hasSlot = hasSlot
|
hasSlot = hasSlot
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ GameObject:
|
|||||||
- component: {fileID: 3435632802124758411}
|
- component: {fileID: 3435632802124758411}
|
||||||
- component: {fileID: 8947209170748834035}
|
- component: {fileID: 8947209170748834035}
|
||||||
- component: {fileID: 7852204877518954380}
|
- component: {fileID: 7852204877518954380}
|
||||||
|
- component: {fileID: 1621671461027776358}
|
||||||
m_Layer: 8
|
m_Layer: 8
|
||||||
m_Name: PulverCharacter
|
m_Name: PulverCharacter
|
||||||
m_TagString: Pulver
|
m_TagString: Pulver
|
||||||
@@ -86,16 +87,10 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: f82afe7b57bd4e0b9f51a1cca06765f1, type: 3}
|
m_Script: {fileID: 11500000, guid: f82afe7b57bd4e0b9f51a1cca06765f1, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
followDistance: 3
|
|
||||||
debugDrawTarget: 1
|
debugDrawTarget: 1
|
||||||
followUpdateInterval: 0.1
|
followUpdateInterval: 0.1
|
||||||
manualMoveSmooth: 5
|
manualMoveSmooth: 100
|
||||||
acceleration: 10
|
justCombined: 0
|
||||||
deceleration: 12
|
|
||||||
thresholdFar: 7
|
|
||||||
thresholdNear: 5
|
|
||||||
stopThreshold: 0.5
|
|
||||||
currentlyHeldItem: {fileID: 0}
|
|
||||||
heldObjectRenderer: {fileID: 2099200424669714683}
|
heldObjectRenderer: {fileID: 2099200424669714683}
|
||||||
--- !u!114 &8947209170748834035
|
--- !u!114 &8947209170748834035
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@@ -162,11 +157,33 @@ MonoBehaviour:
|
|||||||
rotationSpeed: 360
|
rotationSpeed: 360
|
||||||
slowdownDistance: 3
|
slowdownDistance: 3
|
||||||
pickNextWaypointDist: 2
|
pickNextWaypointDist: 2
|
||||||
endReachedDistance: 0.5
|
endReachedDistance: 1
|
||||||
alwaysDrawGizmos: 0
|
alwaysDrawGizmos: 0
|
||||||
slowWhenNotFacingTarget: 1
|
slowWhenNotFacingTarget: 1
|
||||||
whenCloseToDestination: 0
|
whenCloseToDestination: 0
|
||||||
constrainInsideGraph: 0
|
constrainInsideGraph: 0
|
||||||
|
--- !u!114 &1621671461027776358
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1102400833121127473}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: cb6a34d769a1e4ac7b0b30e433aa443c, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
version: 1
|
||||||
|
smoothType: 0
|
||||||
|
subdivisions: 2
|
||||||
|
iterations: 2
|
||||||
|
strength: 0.5
|
||||||
|
uniformLength: 1
|
||||||
|
maxSegmentLength: 2
|
||||||
|
bezierTangentLength: 0.4
|
||||||
|
offset: 0.2
|
||||||
|
factor: 0.1
|
||||||
--- !u!1 &5934518940303293264
|
--- !u!1 &5934518940303293264
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
179
Assets/Prefabs/Items/PrefabsPLACEHOLDER/Bunfflers.prefab
Normal file
179
Assets/Prefabs/Items/PrefabsPLACEHOLDER/Bunfflers.prefab
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &8631570451324008562
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 8737943614546067711}
|
||||||
|
- component: {fileID: 4638897979003302452}
|
||||||
|
- component: {fileID: 2967522604765020532}
|
||||||
|
- component: {fileID: 6501709216426994228}
|
||||||
|
- component: {fileID: 7629925223318462841}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Bunfflers
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &8737943614546067711
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8631570451324008562}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: -23.31, y: -12.06, z: 0}
|
||||||
|
m_LocalScale: {x: 2, y: 2, z: 2}
|
||||||
|
m_ConstrainProportionsScale: 1
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!212 &4638897979003302452
|
||||||
|
SpriteRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8631570451324008562}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_CastShadows: 0
|
||||||
|
m_ReceiveShadows: 0
|
||||||
|
m_DynamicOccludee: 1
|
||||||
|
m_StaticShadowCaster: 0
|
||||||
|
m_MotionVectors: 1
|
||||||
|
m_LightProbeUsage: 1
|
||||||
|
m_ReflectionProbeUsage: 1
|
||||||
|
m_RayTracingMode: 0
|
||||||
|
m_RayTraceProcedural: 0
|
||||||
|
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||||
|
m_RayTracingAccelStructBuildFlags: 1
|
||||||
|
m_SmallMeshCulling: 1
|
||||||
|
m_RenderingLayerMask: 1
|
||||||
|
m_RendererPriority: 0
|
||||||
|
m_Materials:
|
||||||
|
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
||||||
|
m_StaticBatchInfo:
|
||||||
|
firstSubMesh: 0
|
||||||
|
subMeshCount: 0
|
||||||
|
m_StaticBatchRoot: {fileID: 0}
|
||||||
|
m_ProbeAnchor: {fileID: 0}
|
||||||
|
m_LightProbeVolumeOverride: {fileID: 0}
|
||||||
|
m_ScaleInLightmap: 1
|
||||||
|
m_ReceiveGI: 1
|
||||||
|
m_PreserveUVs: 0
|
||||||
|
m_IgnoreNormalsForChartDetection: 0
|
||||||
|
m_ImportantGI: 0
|
||||||
|
m_StitchLightmapSeams: 1
|
||||||
|
m_SelectedEditorRenderState: 0
|
||||||
|
m_MinimumChartSize: 4
|
||||||
|
m_AutoUVMaxDistance: 0.5
|
||||||
|
m_AutoUVMaxAngle: 89
|
||||||
|
m_LightmapParameters: {fileID: 0}
|
||||||
|
m_SortingLayerID: 0
|
||||||
|
m_SortingLayer: 0
|
||||||
|
m_SortingOrder: 0
|
||||||
|
m_Sprite: {fileID: -8848419083337551572, guid: b285cfb6530624a44a95ec99a59d7215, type: 3}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_FlipX: 0
|
||||||
|
m_FlipY: 0
|
||||||
|
m_DrawMode: 0
|
||||||
|
m_Size: {x: 1.74, y: 1.59}
|
||||||
|
m_AdaptiveModeThreshold: 0.5
|
||||||
|
m_SpriteTileMode: 0
|
||||||
|
m_WasSpriteAssigned: 1
|
||||||
|
m_MaskInteraction: 0
|
||||||
|
m_SpriteSortPoint: 0
|
||||||
|
--- !u!61 &2967522604765020532
|
||||||
|
BoxCollider2D:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8631570451324008562}
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 3
|
||||||
|
m_Density: 1
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_IncludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_ExcludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_LayerOverridePriority: 0
|
||||||
|
m_ForceSendLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 4294967295
|
||||||
|
m_ForceReceiveLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 4294967295
|
||||||
|
m_ContactCaptureLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 4294967295
|
||||||
|
m_CallbackLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 4294967295
|
||||||
|
m_IsTrigger: 0
|
||||||
|
m_UsedByEffector: 0
|
||||||
|
m_CompositeOperation: 0
|
||||||
|
m_CompositeOrder: 0
|
||||||
|
m_Offset: {x: 0.00000047683716, y: -0.06357646}
|
||||||
|
m_SpriteTilingProperty:
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
pivot: {x: 0.5, y: 0.5}
|
||||||
|
oldSize: {x: 1.74, y: 1.59}
|
||||||
|
newSize: {x: 1.74, y: 1.59}
|
||||||
|
adaptiveTilingThreshold: 0.5
|
||||||
|
drawMode: 0
|
||||||
|
adaptiveTiling: 0
|
||||||
|
m_AutoTiling: 0
|
||||||
|
m_Size: {x: 3.011527, y: 2.861527}
|
||||||
|
m_EdgeRadius: 0
|
||||||
|
--- !u!114 &6501709216426994228
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8631570451324008562}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 73d6494a73174ffabc6a7d3089d51e73, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
isOneTime: 0
|
||||||
|
cooldown: -1
|
||||||
|
characterToInteract: 0
|
||||||
|
interactionStarted:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
interactionInterrupted:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
characterArrived:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
interactionComplete:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
--- !u!114 &7629925223318462841
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8631570451324008562}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 7846448751da4bdbaaa5cb87890dca42, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
itemData: {fileID: 11400000, guid: 6934dcb56c610c44da228f7f24ca13c9, type: 2}
|
||||||
|
iconRenderer: {fileID: 4638897979003302452}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 47ac9229b9b128041a770b193eb43b02
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -190,7 +190,7 @@ Transform:
|
|||||||
m_GameObject: {fileID: 100481742}
|
m_GameObject: {fileID: 100481742}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
m_LocalPosition: {x: -4, y: 0, z: -10}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
@@ -299,6 +299,10 @@ PrefabInstance:
|
|||||||
propertyPath: stepData
|
propertyPath: stepData
|
||||||
value:
|
value:
|
||||||
objectReference: {fileID: 11400000, guid: 13b0c411066f85a41ba40c3bbbc281ed, type: 2}
|
objectReference: {fileID: 11400000, guid: 13b0c411066f85a41ba40c3bbbc281ed, type: 2}
|
||||||
|
- target: {fileID: 6254953093500072797, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 6303063351359542479, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
- target: {fileID: 6303063351359542479, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
propertyPath: m_Sprite
|
propertyPath: m_Sprite
|
||||||
value:
|
value:
|
||||||
@@ -494,6 +498,10 @@ PrefabInstance:
|
|||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: Quarry
|
value: Quarry
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8086761134767870039, guid: 539b408cd1191614abdcd99506f1157d, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 9191656170436146298, guid: 539b408cd1191614abdcd99506f1157d, type: 3}
|
- target: {fileID: 9191656170436146298, guid: 539b408cd1191614abdcd99506f1157d, type: 3}
|
||||||
propertyPath: m_Sprite
|
propertyPath: m_Sprite
|
||||||
value:
|
value:
|
||||||
@@ -567,17 +575,23 @@ PrefabInstance:
|
|||||||
propertyPath: m_Enabled
|
propertyPath: m_Enabled
|
||||||
value: 1
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 6254953093500072797, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
|
propertyPath: isOneTime
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 6254953093500072797, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 6350287859698694726, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
- target: {fileID: 6350287859698694726, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: TestAss
|
value: TestAss
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents:
|
||||||
|
- {fileID: 4778083634590203921, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
m_AddedComponents:
|
m_AddedComponents: []
|
||||||
- targetCorrespondingSourceObject: {fileID: 6350287859698694726, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
|
||||||
insertIndex: -1
|
|
||||||
addedObject: {fileID: 800207724}
|
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
m_SourcePrefab: {fileID: 100100000, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
--- !u!1 &384576743
|
--- !u!1 &384576743
|
||||||
GameObject:
|
GameObject:
|
||||||
@@ -737,6 +751,10 @@ PrefabInstance:
|
|||||||
propertyPath: stepData
|
propertyPath: stepData
|
||||||
value:
|
value:
|
||||||
objectReference: {fileID: 11400000, guid: 9de0c57af6191384e96e2ba7c04a3d0d, type: 2}
|
objectReference: {fileID: 11400000, guid: 9de0c57af6191384e96e2ba7c04a3d0d, type: 2}
|
||||||
|
- target: {fileID: 6254953093500072797, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 6303063351359542479, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
- target: {fileID: 6303063351359542479, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
propertyPath: m_Sprite
|
propertyPath: m_Sprite
|
||||||
value:
|
value:
|
||||||
@@ -755,29 +773,6 @@ Transform:
|
|||||||
m_CorrespondingSourceObject: {fileID: 2844046668579196942, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
m_CorrespondingSourceObject: {fileID: 2844046668579196942, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
m_PrefabInstance: {fileID: 368640488}
|
m_PrefabInstance: {fileID: 368640488}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
--- !u!1 &800207718 stripped
|
|
||||||
GameObject:
|
|
||||||
m_CorrespondingSourceObject: {fileID: 6350287859698694726, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
|
||||||
m_PrefabInstance: {fileID: 368640488}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
--- !u!114 &800207724
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 800207718}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 21401a3b30134380bb205964d9e5c67d, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
OnSuccess:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
OnFailure:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
--- !u!1 &948124904
|
--- !u!1 &948124904
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -868,7 +863,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: c119ffb87b2a16d4f925ff5d5ffd7092, type: 3}
|
m_Script: {fileID: 11500000, guid: c119ffb87b2a16d4f925ff5d5ffd7092, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
ShouldPlayIntro: 1
|
shouldPlayIntro: 0
|
||||||
--- !u!95 &948124911
|
--- !u!95 &948124911
|
||||||
Animator:
|
Animator:
|
||||||
serializedVersion: 7
|
serializedVersion: 7
|
||||||
@@ -982,6 +977,10 @@ PrefabInstance:
|
|||||||
propertyPath: stepData
|
propertyPath: stepData
|
||||||
value:
|
value:
|
||||||
objectReference: {fileID: 11400000, guid: a84cbe9804e13f74e857c55d90cc10d1, type: 2}
|
objectReference: {fileID: 11400000, guid: a84cbe9804e13f74e857c55d90cc10d1, type: 2}
|
||||||
|
- target: {fileID: 6254953093500072797, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 6303063351359542479, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
- target: {fileID: 6303063351359542479, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
propertyPath: m_Sprite
|
propertyPath: m_Sprite
|
||||||
value:
|
value:
|
||||||
@@ -1103,6 +1102,10 @@ PrefabInstance:
|
|||||||
propertyPath: m_WasSpriteAssigned
|
propertyPath: m_WasSpriteAssigned
|
||||||
value: 1
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7616859841301711022, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
@@ -1446,7 +1449,16 @@ PrefabInstance:
|
|||||||
propertyPath: m_WasSpriteAssigned
|
propertyPath: m_WasSpriteAssigned
|
||||||
value: 1
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
- target: {fileID: 7616859841301711022, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
|
propertyPath: isOneTime
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7616859841301711022, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
m_RemovedComponents:
|
||||||
|
- {fileID: 592045584872845087, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects:
|
m_AddedGameObjects:
|
||||||
- targetCorrespondingSourceObject: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
- targetCorrespondingSourceObject: {fileID: 1730119453103664125, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
@@ -1562,37 +1574,15 @@ PrefabInstance:
|
|||||||
propertyPath: m_WasSpriteAssigned
|
propertyPath: m_WasSpriteAssigned
|
||||||
value: 1
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7616859841301711022, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
|
propertyPath: characterToInteract
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
m_AddedComponents:
|
m_AddedComponents: []
|
||||||
- targetCorrespondingSourceObject: {fileID: 7447346505753002421, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
|
||||||
insertIndex: -1
|
|
||||||
addedObject: {fileID: 1578994557}
|
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
m_SourcePrefab: {fileID: 100100000, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
--- !u!1 &1578994556 stripped
|
|
||||||
GameObject:
|
|
||||||
m_CorrespondingSourceObject: {fileID: 7447346505753002421, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
|
||||||
m_PrefabInstance: {fileID: 1578994555}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
--- !u!114 &1578994557
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1578994556}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 21401a3b30134380bb205964d9e5c67d, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
OnSuccess:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
OnFailure:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
--- !u!4 &1627665103 stripped
|
--- !u!4 &1627665103 stripped
|
||||||
Transform:
|
Transform:
|
||||||
m_CorrespondingSourceObject: {fileID: 2844046668579196942, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
m_CorrespondingSourceObject: {fileID: 2844046668579196942, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
|
||||||
@@ -1620,14 +1610,14 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: ec1a2e6e32f746c4990c579e13b79104, type: 3}
|
m_Script: {fileID: 11500000, guid: ec1a2e6e32f746c4990c579e13b79104, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
OnSuccess:
|
itemData: {fileID: 11400000, guid: e0fad48a84a6b6346ac17c84bc512500, type: 2}
|
||||||
m_PersistentCalls:
|
iconRenderer: {fileID: 1631660128}
|
||||||
m_Calls: []
|
|
||||||
OnFailure:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
currentlySlottedItem: {fileID: 0}
|
|
||||||
slottedItemRenderer: {fileID: 124275613}
|
slottedItemRenderer: {fileID: 124275613}
|
||||||
|
--- !u!212 &1631660128 stripped
|
||||||
|
SpriteRenderer:
|
||||||
|
m_CorrespondingSourceObject: {fileID: 7494677664706785084, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
|
||||||
|
m_PrefabInstance: {fileID: 1336824707}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
--- !u!1 &1741016587
|
--- !u!1 &1741016587
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1716,7 +1706,7 @@ Transform:
|
|||||||
m_GameObject: {fileID: 1741016587}
|
m_GameObject: {fileID: 1741016587}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
m_LocalPosition: {x: -4, y: 0, z: -10}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
@@ -1974,30 +1964,6 @@ PrefabInstance:
|
|||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3435632802124758411, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
|
||||||
propertyPath: acceleration
|
|
||||||
value: 15
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 3435632802124758411, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
|
||||||
propertyPath: thresholdFar
|
|
||||||
value: 12
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 3435632802124758411, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
|
||||||
propertyPath: thresholdNear
|
|
||||||
value: 7
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 3435632802124758411, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
|
||||||
propertyPath: followDistance
|
|
||||||
value: 5
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 3435632802124758411, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
|
||||||
propertyPath: manualMoveSmooth
|
|
||||||
value: 100
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 3435632802124758411, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
|
||||||
propertyPath: heldIconDisplayHeight
|
|
||||||
value: 2
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
@@ -2013,7 +1979,7 @@ PrefabInstance:
|
|||||||
m_Modifications:
|
m_Modifications:
|
||||||
- target: {fileID: 3823830588451517910, guid: 301b4e0735896334f8f6fb9a68a7e419, type: 3}
|
- target: {fileID: 3823830588451517910, guid: 301b4e0735896334f8f6fb9a68a7e419, type: 3}
|
||||||
propertyPath: m_LocalPosition.x
|
propertyPath: m_LocalPosition.x
|
||||||
value: 0
|
value: -4
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3823830588451517910, guid: 301b4e0735896334f8f6fb9a68a7e419, type: 3}
|
- target: {fileID: 3823830588451517910, guid: 301b4e0735896334f8f6fb9a68a7e419, type: 3}
|
||||||
propertyPath: m_LocalPosition.y
|
propertyPath: m_LocalPosition.y
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class GameManager : MonoBehaviour
|
|||||||
public float ManualMoveSmooth => gameSettings != null ? gameSettings.manualMoveSmooth : 8f;
|
public float ManualMoveSmooth => gameSettings != null ? gameSettings.manualMoveSmooth : 8f;
|
||||||
public float ThresholdFar => gameSettings != null ? gameSettings.thresholdFar : 2.5f;
|
public float ThresholdFar => gameSettings != null ? gameSettings.thresholdFar : 2.5f;
|
||||||
public float ThresholdNear => gameSettings != null ? gameSettings.thresholdNear : 0.5f;
|
public float ThresholdNear => gameSettings != null ? gameSettings.thresholdNear : 0.5f;
|
||||||
public float StopThreshold => gameSettings != null ? gameSettings.stopThreshold : 0.1f;
|
public float StopThreshold => gameSettings != null ? gameSettings.stopThreshold : 0.5f;
|
||||||
public float MoveSpeed => gameSettings != null ? gameSettings.moveSpeed : 5f;
|
public float MoveSpeed => gameSettings != null ? gameSettings.moveSpeed : 5f;
|
||||||
public float StopDistance => gameSettings != null ? gameSettings.stopDistance : 0.1f;
|
public float StopDistance => gameSettings != null ? gameSettings.stopDistance : 0.1f;
|
||||||
public bool UseRigidbody => gameSettings != null ? gameSettings.useRigidbody : true;
|
public bool UseRigidbody => gameSettings != null ? gameSettings.useRigidbody : true;
|
||||||
@@ -59,6 +59,7 @@ public class GameManager : MonoBehaviour
|
|||||||
public float HeldIconDisplayHeight => gameSettings != null ? gameSettings.heldIconDisplayHeight : 2.0f;
|
public float HeldIconDisplayHeight => gameSettings != null ? gameSettings.heldIconDisplayHeight : 2.0f;
|
||||||
public GameObject BasePickupPrefab => gameSettings != null ? gameSettings.basePickupPrefab : null;
|
public GameObject BasePickupPrefab => gameSettings != null ? gameSettings.basePickupPrefab : null;
|
||||||
public LayerMask InteractableLayerMask => gameSettings != null ? gameSettings.interactableLayerMask : -1;
|
public LayerMask InteractableLayerMask => gameSettings != null ? gameSettings.interactableLayerMask : -1;
|
||||||
|
public float PlayerStopDistanceDirectInteraction => gameSettings != null ? gameSettings.playerStopDistanceDirectInteraction : 2.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the combination rule for two items, if any.
|
/// Returns the combination rule for two items, if any.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public class GameSettings : ScriptableObject
|
|||||||
{
|
{
|
||||||
[Header("Interactions")]
|
[Header("Interactions")]
|
||||||
public float playerStopDistance = 6.0f;
|
public float playerStopDistance = 6.0f;
|
||||||
|
public float playerStopDistanceDirectInteraction = 2.0f;
|
||||||
public float followerPickupDelay = 0.2f;
|
public float followerPickupDelay = 0.2f;
|
||||||
|
|
||||||
[Header("Follower Settings")]
|
[Header("Follower Settings")]
|
||||||
|
|||||||
3
Assets/Scripts/Data.meta
Normal file
3
Assets/Scripts/Data.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e0b15b90103942c3b0e630462ecc5de1
|
||||||
|
timeCreated: 1757518020
|
||||||
1
Assets/Scripts/Data/ItemCombinationManager.cs
Normal file
1
Assets/Scripts/Data/ItemCombinationManager.cs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
3
Assets/Scripts/Data/ItemCombinationManager.cs.meta
Normal file
3
Assets/Scripts/Data/ItemCombinationManager.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a54fc1a3945f46c580a83e74f9436526
|
||||||
|
timeCreated: 1757518020
|
||||||
@@ -157,17 +157,14 @@ public class InputManager : MonoBehaviour
|
|||||||
Collider2D hit = Physics2D.OverlapPoint(worldPos, mask);
|
Collider2D hit = Physics2D.OverlapPoint(worldPos, mask);
|
||||||
if (hit != null)
|
if (hit != null)
|
||||||
{
|
{
|
||||||
var interactable = hit.GetComponent<ITouchInputConsumer>();
|
var consumer = hit.GetComponent<ITouchInputConsumer>();
|
||||||
if (interactable != null)
|
if (consumer != null)
|
||||||
{
|
{
|
||||||
Debug.unityLogger.Log("Interactable", $"[InputManager] Delegating tap to interactable at {worldPos} (GameObject: {hit.gameObject.name})");
|
Debug.unityLogger.Log("Interactable", $"[InputManager] Delegating tap to consumer at {worldPos} (GameObject: {hit.gameObject.name})");
|
||||||
interactable.OnTap(worldPos);
|
consumer.OnTap(worldPos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
Debug.unityLogger.Log("Interactable", $"[InputManager] Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found.");
|
||||||
{
|
|
||||||
Debug.unityLogger.Log("Interactable", $"[InputManager] Collider2D hit at {worldPos} (GameObject: {hit.gameObject.name}), but no ITouchInputConsumer found.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction requirement that allows combining the follower's held item with this pickup if a valid combination rule exists.
|
|
||||||
/// </summary>
|
|
||||||
[RequireComponent(typeof(Pickup))]
|
|
||||||
public class CombineWithBehavior : InteractionRequirementBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to combine the follower's held item with this pickup's item.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="follower">The follower attempting the interaction.</param>
|
|
||||||
/// <returns>True if the combination was successful, false otherwise.</returns>
|
|
||||||
public override bool TryInteract(FollowerController follower)
|
|
||||||
{
|
|
||||||
var heldItem = follower.CurrentlyHeldItem;
|
|
||||||
var pickup = GetComponent<Pickup>();
|
|
||||||
if (heldItem == null)
|
|
||||||
{
|
|
||||||
// DebugUIMessage.Show("You need an item to combine.");
|
|
||||||
OnFailure?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (pickup == null || pickup.itemData == null)
|
|
||||||
{
|
|
||||||
DebugUIMessage.Show("Target item is missing or invalid.");
|
|
||||||
OnFailure?.Invoke();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var rule = GameManager.Instance.GetCombinationRule(heldItem, pickup.itemData);
|
|
||||||
if (rule != null && rule.resultPrefab != null)
|
|
||||||
{
|
|
||||||
// Instantiate the result prefab at the pickup's position
|
|
||||||
var resultObj = GameObject.Instantiate(rule.resultPrefab, pickup.transform.position, Quaternion.identity);
|
|
||||||
var resultPickup = resultObj.GetComponent<Pickup>();
|
|
||||||
if (resultPickup != null)
|
|
||||||
{
|
|
||||||
// Hide and parent to follower
|
|
||||||
resultObj.SetActive(false);
|
|
||||||
resultObj.transform.SetParent(follower.transform);
|
|
||||||
// Set held item and icon from the spawned prefab
|
|
||||||
follower.SetHeldItem(resultPickup.itemData, resultPickup.iconRenderer);
|
|
||||||
// Cache the spawned object as the held item
|
|
||||||
follower.CacheHeldPickupObject(resultObj);
|
|
||||||
follower.justCombined = true;
|
|
||||||
OnSuccess?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogWarning("Result prefab does not have a Pickup component.");
|
|
||||||
GameObject.Destroy(resultObj);
|
|
||||||
OnFailure?.Invoke();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// DebugUIMessage.Show($"Cannot combine {heldItem.itemName ?? \"an item\"} with {pickup.itemData.itemName ?? \"target item\"}.");
|
|
||||||
OnFailure?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 21401a3b30134380bb205964d9e5c67d
|
|
||||||
timeCreated: 1756981777
|
|
||||||
@@ -1,76 +1,230 @@
|
|||||||
using UnityEngine;
|
using Input;
|
||||||
|
using UnityEngine;
|
||||||
using System;
|
using System;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
|
||||||
/// <summary>
|
namespace Interactions
|
||||||
/// Represents an interactable object that can respond to tap input events.
|
|
||||||
/// </summary>
|
|
||||||
public class Interactable : MonoBehaviour, ITouchInputConsumer
|
|
||||||
{
|
{
|
||||||
public event Action StartedInteraction;
|
public enum CharacterToInteract
|
||||||
public event Action<bool> InteractionComplete;
|
|
||||||
|
|
||||||
private ObjectiveStepBehaviour stepBehaviour;
|
|
||||||
|
|
||||||
void Awake()
|
|
||||||
{
|
{
|
||||||
stepBehaviour = GetComponent<ObjectiveStepBehaviour>();
|
Trafalgar,
|
||||||
|
Pulver
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles tap input. Triggers interaction logic.
|
/// Represents an interactable object that can respond to tap input events.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnTap(Vector2 worldPosition)
|
public class Interactable : MonoBehaviour, ITouchInputConsumer
|
||||||
{
|
{
|
||||||
Debug.Log($"[Interactable] OnTap at {worldPosition} on {gameObject.name}");
|
[Header("Interaction Settings")]
|
||||||
StartedInteraction?.Invoke();
|
public bool isOneTime = false;
|
||||||
}
|
public float cooldown = -1f;
|
||||||
|
public CharacterToInteract characterToInteract = CharacterToInteract.Pulver;
|
||||||
|
|
||||||
|
[Header("Interaction Events")]
|
||||||
|
public UnityEvent<PlayerTouchController, FollowerController> interactionStarted;
|
||||||
|
public UnityEvent interactionInterrupted;
|
||||||
|
public UnityEvent characterArrived;
|
||||||
|
public UnityEvent<bool> interactionComplete;
|
||||||
|
|
||||||
/// <summary>
|
// Helpers for managing interaction state
|
||||||
/// No hold behavior for interactables.
|
private bool _interactionInProgress;
|
||||||
/// </summary>
|
private PlayerTouchController _playerRef;
|
||||||
public void OnHoldStart(Vector2 worldPosition) { }
|
private FollowerController _followerController;
|
||||||
public void OnHoldMove(Vector2 worldPosition) { }
|
|
||||||
public void OnHoldEnd(Vector2 worldPosition) { }
|
|
||||||
|
|
||||||
/// <summary>
|
private bool _isActive = true;
|
||||||
/// Called when the follower arrives at this interactable.
|
|
||||||
/// </summary>
|
private void Awake()
|
||||||
public bool OnFollowerArrived(FollowerController follower)
|
|
||||||
{
|
|
||||||
// Check if step is locked here
|
|
||||||
if (stepBehaviour != null && !stepBehaviour.IsStepUnlocked())
|
|
||||||
{
|
{
|
||||||
DebugUIMessage.Show("Item is not unlocked yet");
|
// Subscribe to interactionComplete event
|
||||||
Debug.Log("[Puzzles] Tried to interact with locked step: " + gameObject.name);
|
interactionComplete.AddListener(OnInteractionComplete);
|
||||||
InteractionComplete?.Invoke(false);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
var requirements = GetComponents<InteractionRequirementBase>();
|
|
||||||
if (requirements.Length == 0)
|
/// <summary>
|
||||||
|
/// Handles tap input. Triggers interaction logic.
|
||||||
|
/// </summary>
|
||||||
|
public void OnTap(Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
InteractionComplete?.Invoke(true);
|
if (!_isActive)
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool anySuccess = false;
|
|
||||||
foreach (var req in requirements)
|
|
||||||
{
|
|
||||||
if (req.TryInteract(follower))
|
|
||||||
{
|
{
|
||||||
anySuccess = true;
|
Debug.Log($"[Interactable] Is disabled!");
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
Debug.Log($"[Interactable] OnTap at {worldPosition} on {gameObject.name}");
|
||||||
|
// Broadcast interaction started event
|
||||||
|
TryInteract();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TryInteract()
|
||||||
|
{
|
||||||
|
_interactionInProgress = true;
|
||||||
|
|
||||||
|
_playerRef = FindFirstObjectByType<PlayerTouchController>();
|
||||||
|
_followerController = FindFirstObjectByType<FollowerController>();
|
||||||
|
|
||||||
|
interactionStarted?.Invoke(_playerRef, _followerController);
|
||||||
|
|
||||||
|
if (_playerRef == null)
|
||||||
|
{
|
||||||
|
Debug.Log($"[Interactable] Player character could not be found. Aborting interaction.");
|
||||||
|
interactionInterrupted.Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute closest point on the interaction radius
|
||||||
|
Vector3 interactablePos = transform.position;
|
||||||
|
Vector3 playerPos = _playerRef.transform.position;
|
||||||
|
float stopDistance = characterToInteract == CharacterToInteract.Pulver
|
||||||
|
? GameManager.Instance.PlayerStopDistance
|
||||||
|
: GameManager.Instance.PlayerStopDistanceDirectInteraction;
|
||||||
|
Vector3 toPlayer = (playerPos - interactablePos).normalized;
|
||||||
|
Vector3 stopPoint = interactablePos + toPlayer * stopDistance;
|
||||||
|
|
||||||
|
// Unsubscribe previous to avoid duplicate calls
|
||||||
|
_playerRef.OnArrivedAtTarget -= OnPlayerArrived;
|
||||||
|
_playerRef.OnMoveToCancelled -= OnPlayerMoveCancelled;
|
||||||
|
_playerRef.OnArrivedAtTarget += OnPlayerArrived;
|
||||||
|
_playerRef.OnMoveToCancelled += OnPlayerMoveCancelled;
|
||||||
|
_playerRef.MoveToAndNotify(stopPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerMoveCancelled()
|
||||||
|
{
|
||||||
|
_interactionInProgress = false;
|
||||||
|
interactionInterrupted?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerArrived()
|
||||||
|
{
|
||||||
|
if (!_interactionInProgress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Unsubscribe to avoid memory leaks
|
||||||
|
_playerRef.OnArrivedAtTarget -= OnPlayerArrived;
|
||||||
|
|
||||||
|
if (characterToInteract == CharacterToInteract.Pulver)
|
||||||
|
{
|
||||||
|
_followerController.OnPickupArrived -= OnFollowerArrived;
|
||||||
|
_followerController.OnPickupArrived += OnFollowerArrived;
|
||||||
|
_followerController.GoToPointAndReturn(transform.position, _playerRef.transform);
|
||||||
|
}
|
||||||
|
else if (characterToInteract == CharacterToInteract.Trafalgar)
|
||||||
|
{
|
||||||
|
BroadcastCharacterArrived();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InteractionComplete?.Invoke(anySuccess);
|
|
||||||
if (!anySuccess)
|
|
||||||
{
|
|
||||||
Debug.Log($"[Interactable] No interaction requirements succeeded for {gameObject.name}");
|
|
||||||
// Optionally trigger a default failure event or feedback here
|
|
||||||
}
|
|
||||||
return anySuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CompleteInteraction(bool success)
|
private void OnFollowerArrived()
|
||||||
{
|
{
|
||||||
InteractionComplete?.Invoke(success);
|
if (!_interactionInProgress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Unsubscribe to avoid memory leaks
|
||||||
|
_followerController.OnPickupArrived -= OnFollowerArrived;
|
||||||
|
|
||||||
|
BroadcastCharacterArrived();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BroadcastCharacterArrived()
|
||||||
|
{
|
||||||
|
// Check for ObjectiveStepBehaviour and lock state
|
||||||
|
var step = GetComponent<PuzzleS.ObjectiveStepBehaviour>();
|
||||||
|
if (step != null && !step.IsStepUnlocked())
|
||||||
|
{
|
||||||
|
DebugUIMessage.Show("This step is locked!", 2f);
|
||||||
|
BroadcastInteractionComplete(false);
|
||||||
|
// Reset variables for next time
|
||||||
|
_interactionInProgress = false;
|
||||||
|
_playerRef = null;
|
||||||
|
_followerController = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Broadcast appropriate event
|
||||||
|
characterArrived?.Invoke();
|
||||||
|
// Reset variables for next time
|
||||||
|
_interactionInProgress = false;
|
||||||
|
_playerRef = null;
|
||||||
|
_followerController = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInteractionComplete(bool success)
|
||||||
|
{
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
if (isOneTime)
|
||||||
|
{
|
||||||
|
_isActive = false;
|
||||||
|
}
|
||||||
|
else if (cooldown >= 0f)
|
||||||
|
{
|
||||||
|
StartCoroutine(HandleCooldown());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private System.Collections.IEnumerator HandleCooldown()
|
||||||
|
{
|
||||||
|
_isActive = false;
|
||||||
|
yield return new WaitForSeconds(cooldown);
|
||||||
|
_isActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnHoldStart(Vector2 position)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnHoldMove(Vector2 position)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnHoldEnd(Vector2 position)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BroadcastInteractionComplete(bool success)
|
||||||
|
{
|
||||||
|
interactionComplete?.Invoke(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
/// <summary>
|
||||||
|
/// Draws gizmos for pickup interaction range in the editor.
|
||||||
|
/// </summary>
|
||||||
|
void OnDrawGizmos()
|
||||||
|
{
|
||||||
|
float playerStopDistance;
|
||||||
|
if (Application.isPlaying)
|
||||||
|
{
|
||||||
|
playerStopDistance = characterToInteract == CharacterToInteract.Trafalgar
|
||||||
|
? GameManager.Instance.PlayerStopDistanceDirectInteraction
|
||||||
|
: GameManager.Instance.PlayerStopDistance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load settings directly from asset path in editor
|
||||||
|
var settings =
|
||||||
|
UnityEditor.AssetDatabase.LoadAssetAtPath<GameSettings>(
|
||||||
|
"Assets/Data/Settings/DefaultSettings.asset");
|
||||||
|
playerStopDistance = settings != null
|
||||||
|
? (characterToInteract == CharacterToInteract.Trafalgar
|
||||||
|
? settings.playerStopDistanceDirectInteraction
|
||||||
|
: settings.playerStopDistance)
|
||||||
|
: 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gizmos.color = Color.yellow;
|
||||||
|
Gizmos.DrawWireSphere(transform.position, playerStopDistance);
|
||||||
|
GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
|
||||||
|
if (playerObj != null)
|
||||||
|
{
|
||||||
|
Vector3 stopPoint = transform.position +
|
||||||
|
(playerObj.transform.position - transform.position).normalized * playerStopDistance;
|
||||||
|
Gizmos.color = Color.cyan;
|
||||||
|
Gizmos.DrawSphere(stopPoint, 0.15f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
145
Assets/Scripts/Interactions/ItemSlot.cs
Normal file
145
Assets/Scripts/Interactions/ItemSlot.cs
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Interactions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction requirement that allows slotting, swapping, or picking up items in a slot.
|
||||||
|
/// </summary>
|
||||||
|
[RequireComponent(typeof(Interactable))]
|
||||||
|
public class ItemSlot : Pickup
|
||||||
|
{
|
||||||
|
private PickupItemData _currentlySlottedItemData;
|
||||||
|
public SpriteRenderer slottedItemRenderer;
|
||||||
|
private GameObject _currentlySlottedItemObject = null;
|
||||||
|
|
||||||
|
|
||||||
|
public GameObject GetSlottedObject()
|
||||||
|
{
|
||||||
|
return _currentlySlottedItemObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSlottedObject(GameObject obj)
|
||||||
|
{
|
||||||
|
_currentlySlottedItemObject = obj;
|
||||||
|
if (_currentlySlottedItemObject != null)
|
||||||
|
{
|
||||||
|
_currentlySlottedItemObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnCharacterArrived()
|
||||||
|
{
|
||||||
|
var heldItemData = FollowerController.CurrentlyHeldItemData;
|
||||||
|
var heldItemObj = FollowerController.GetHeldPickupObject();
|
||||||
|
var pickup = GetComponent<Pickup>();
|
||||||
|
var slotItem = pickup != null ? pickup.itemData : null;
|
||||||
|
var config = GameManager.Instance.GetSlotItemConfig(slotItem);
|
||||||
|
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
||||||
|
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
|
||||||
|
|
||||||
|
if ((heldItemData == null && _currentlySlottedItemObject != null)
|
||||||
|
|| (heldItemData != null && _currentlySlottedItemObject != null))
|
||||||
|
{
|
||||||
|
FollowerController.TryPickupItem(_currentlySlottedItemObject, _currentlySlottedItemData);
|
||||||
|
_currentlySlottedItemObject = null;
|
||||||
|
_currentlySlottedItemData = null;
|
||||||
|
UpdateSlottedSprite();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // CASE 1: No held item, slot has item -> pick up slotted item
|
||||||
|
// if (heldItemData == null && _cachedSlottedObject != null)
|
||||||
|
// {
|
||||||
|
// InteractionOrchestrator.Instance.PickupItem(FollowerController, _cachedSlottedObject);
|
||||||
|
// _cachedSlottedObject = null;
|
||||||
|
// currentlySlottedItem = null;
|
||||||
|
// UpdateSlottedSprite();
|
||||||
|
// Interactable.BroadcastInteractionComplete(false);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// // CASE 2: Held item, slot has item -> swap
|
||||||
|
// if
|
||||||
|
// {
|
||||||
|
// InteractionOrchestrator.Instance.SwapItems(FollowerController, this);
|
||||||
|
// currentlySlottedItem = heldItemData;
|
||||||
|
// UpdateSlottedSprite();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// CASE 3: Held item, slot empty -> slot the held item
|
||||||
|
if (heldItemData != null && _currentlySlottedItemObject == null)
|
||||||
|
{
|
||||||
|
if (forbidden.Contains(heldItemData))
|
||||||
|
{
|
||||||
|
DebugUIMessage.Show("Can't place that here.");
|
||||||
|
Interactable.BroadcastInteractionComplete(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotItem(heldItemObj, heldItemData);
|
||||||
|
if (allowed.Contains(heldItemData))
|
||||||
|
{
|
||||||
|
Interactable.BroadcastInteractionComplete(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugUIMessage.Show("I'm not sure this works.");
|
||||||
|
Interactable.BroadcastInteractionComplete(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASE 4: No held item, slot empty -> show warning
|
||||||
|
if (heldItemData == null && _currentlySlottedItemObject == null)
|
||||||
|
{
|
||||||
|
DebugUIMessage.Show("This requires an item.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the sprite and scale for the currently slotted item.
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateSlottedSprite()
|
||||||
|
{
|
||||||
|
if (slottedItemRenderer != null && _currentlySlottedItemData != null && _currentlySlottedItemData.mapSprite != null)
|
||||||
|
{
|
||||||
|
slottedItemRenderer.sprite = _currentlySlottedItemData.mapSprite;
|
||||||
|
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
|
||||||
|
float desiredHeight = GameManager.Instance.HeldIconDisplayHeight;
|
||||||
|
var sprite = _currentlySlottedItemData.mapSprite;
|
||||||
|
float spriteHeight = sprite.bounds.size.y;
|
||||||
|
float spriteWidth = sprite.bounds.size.x;
|
||||||
|
Vector3 parentScale = slottedItemRenderer.transform.parent != null
|
||||||
|
? slottedItemRenderer.transform.parent.localScale
|
||||||
|
: Vector3.one;
|
||||||
|
if (spriteHeight > 0f)
|
||||||
|
{
|
||||||
|
float uniformScale = desiredHeight / spriteHeight;
|
||||||
|
float scale = uniformScale / Mathf.Max(parentScale.x, parentScale.y);
|
||||||
|
slottedItemRenderer.transform.localScale = new Vector3(scale, scale, 1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (slottedItemRenderer != null)
|
||||||
|
{
|
||||||
|
slottedItemRenderer.sprite = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SlotItem(GameObject itemToSlot, PickupItemData itemToSlotData)
|
||||||
|
{
|
||||||
|
if (itemToSlot == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
itemToSlot.SetActive(false);
|
||||||
|
itemToSlot.transform.SetParent(null);
|
||||||
|
SetSlottedObject(itemToSlot);
|
||||||
|
|
||||||
|
_currentlySlottedItemData = itemToSlotData;
|
||||||
|
UpdateSlottedSprite();
|
||||||
|
FollowerController.ClearHeldItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System;
|
using System;
|
||||||
|
using Input;
|
||||||
|
using Interactions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MonoBehaviour that immediately completes an interaction when started.
|
/// MonoBehaviour that immediately completes an interaction when started.
|
||||||
@@ -13,7 +15,7 @@ public class OneClickInteraction : MonoBehaviour
|
|||||||
interactable = GetComponent<Interactable>();
|
interactable = GetComponent<Interactable>();
|
||||||
if (interactable != null)
|
if (interactable != null)
|
||||||
{
|
{
|
||||||
interactable.StartedInteraction += OnStartedInteraction;
|
interactable.interactionStarted.AddListener(OnInteractionStarted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,15 +23,15 @@ public class OneClickInteraction : MonoBehaviour
|
|||||||
{
|
{
|
||||||
if (interactable != null)
|
if (interactable != null)
|
||||||
{
|
{
|
||||||
interactable.StartedInteraction -= OnStartedInteraction;
|
interactable.interactionStarted.RemoveListener(OnInteractionStarted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStartedInteraction()
|
private void OnInteractionStarted(PlayerTouchController playerRef, FollowerController followerRef)
|
||||||
{
|
{
|
||||||
if (interactable != null)
|
if (interactable != null)
|
||||||
{
|
{
|
||||||
interactable.CompleteInteraction(true);
|
interactable.BroadcastInteractionComplete(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,182 +1,95 @@
|
|||||||
using Input;
|
using Input;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class Pickup : MonoBehaviour
|
namespace Interactions
|
||||||
{
|
{
|
||||||
/// <summary>
|
[RequireComponent(typeof(Interactable))]
|
||||||
/// Data for the pickup item (icon, name, etc).
|
public class Pickup : MonoBehaviour
|
||||||
/// </summary>
|
|
||||||
public PickupItemData itemData;
|
|
||||||
/// <summary>
|
|
||||||
/// Renderer for the pickup icon.
|
|
||||||
/// </summary>
|
|
||||||
public SpriteRenderer iconRenderer;
|
|
||||||
private Interactable interactable;
|
|
||||||
|
|
||||||
private bool pickupInProgress = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unity Awake callback. Sets up icon, interactable, and event handlers.
|
|
||||||
/// </summary>
|
|
||||||
void Awake()
|
|
||||||
{
|
{
|
||||||
if (iconRenderer == null)
|
public PickupItemData itemData;
|
||||||
iconRenderer = GetComponent<SpriteRenderer>();
|
public SpriteRenderer iconRenderer;
|
||||||
interactable = GetComponent<Interactable>();
|
protected Interactable Interactable;
|
||||||
if (interactable != null)
|
private PlayerTouchController _playerRef;
|
||||||
|
protected FollowerController FollowerController;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unity Awake callback. Sets up icon, interactable, and event handlers.
|
||||||
|
/// </summary>
|
||||||
|
void Awake()
|
||||||
{
|
{
|
||||||
interactable.StartedInteraction += OnStartedInteraction;
|
if (iconRenderer == null)
|
||||||
interactable.InteractionComplete += OnInteractionComplete;
|
iconRenderer = GetComponent<SpriteRenderer>();
|
||||||
}
|
|
||||||
ApplyItemData();
|
Interactable = GetComponent<Interactable>();
|
||||||
}
|
if (Interactable != null)
|
||||||
|
{
|
||||||
|
Interactable.interactionStarted.AddListener(OnInteractionStarted);
|
||||||
|
Interactable.characterArrived.AddListener(OnCharacterArrived);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
ApplyItemData();
|
||||||
/// Unity OnDestroy callback. Cleans up event handlers.
|
}
|
||||||
/// </summary>
|
|
||||||
void OnDestroy()
|
/// <summary>
|
||||||
{
|
/// Unity OnDestroy callback. Cleans up event handlers.
|
||||||
if (interactable != null)
|
/// </summary>
|
||||||
{
|
void OnDestroy()
|
||||||
interactable.StartedInteraction -= OnStartedInteraction;
|
{
|
||||||
interactable.InteractionComplete -= OnInteractionComplete;
|
if (Interactable != null)
|
||||||
|
{
|
||||||
|
Interactable.interactionStarted.RemoveListener(OnInteractionStarted);
|
||||||
|
Interactable.characterArrived.RemoveListener(OnCharacterArrived);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unity OnValidate callback. Ensures icon and data are up to date in editor.
|
/// Unity OnValidate callback. Ensures icon and data are up to date in editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void OnValidate()
|
void OnValidate()
|
||||||
{
|
|
||||||
if (iconRenderer == null)
|
|
||||||
iconRenderer = GetComponent<SpriteRenderer>();
|
|
||||||
ApplyItemData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws gizmos for pickup interaction range in the editor.
|
|
||||||
/// </summary>
|
|
||||||
void OnDrawGizmos()
|
|
||||||
{
|
|
||||||
float playerStopDistance;
|
|
||||||
if (Application.isPlaying)
|
|
||||||
{
|
{
|
||||||
playerStopDistance = GameManager.Instance.PlayerStopDistance;
|
if (iconRenderer == null)
|
||||||
|
iconRenderer = GetComponent<SpriteRenderer>();
|
||||||
|
ApplyItemData();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Load settings directly from asset path in editor
|
|
||||||
var settings = UnityEditor.AssetDatabase.LoadAssetAtPath<GameSettings>("Assets/Data/Settings/DefaultSettings.asset");
|
|
||||||
playerStopDistance = settings != null ? settings.playerStopDistance : 1.0f;
|
|
||||||
}
|
|
||||||
Gizmos.color = Color.yellow;
|
|
||||||
Gizmos.DrawWireSphere(transform.position, playerStopDistance);
|
|
||||||
GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
|
|
||||||
if (playerObj != null)
|
|
||||||
{
|
|
||||||
Vector3 stopPoint = transform.position + (playerObj.transform.position - transform.position).normalized * playerStopDistance;
|
|
||||||
Gizmos.color = Color.cyan;
|
|
||||||
Gizmos.DrawSphere(stopPoint, 0.15f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies the item data to the pickup (icon, name, etc).
|
/// Applies the item data to the pickup (icon, name, etc).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ApplyItemData()
|
public void ApplyItemData()
|
||||||
{
|
|
||||||
if (itemData != null)
|
|
||||||
{
|
{
|
||||||
if (iconRenderer != null && itemData.mapSprite != null)
|
if (itemData != null)
|
||||||
{
|
{
|
||||||
iconRenderer.sprite = itemData.mapSprite;
|
if (iconRenderer != null && itemData.mapSprite != null)
|
||||||
}
|
{
|
||||||
gameObject.name = itemData.itemName;
|
iconRenderer.sprite = itemData.mapSprite;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
gameObject.name = itemData.itemName;
|
||||||
/// Handles the start of an interaction (player approaches, then follower picks up).
|
}
|
||||||
/// </summary>
|
|
||||||
private void OnStartedInteraction()
|
|
||||||
{
|
|
||||||
if (pickupInProgress) return;
|
|
||||||
var playerObj = GameObject.FindGameObjectWithTag("Player");
|
|
||||||
var followerObj = GameObject.FindGameObjectWithTag("Pulver");
|
|
||||||
if (playerObj == null || followerObj == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("Pickup: Player or Follower not found.");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var playerController = playerObj.GetComponent<PlayerTouchController>();
|
|
||||||
var followerController = followerObj.GetComponent<FollowerController>();
|
/// <summary>
|
||||||
if (playerController == null || followerController == null)
|
/// Handles the start of an interaction (for feedback/UI only).
|
||||||
|
/// </summary>
|
||||||
|
private void OnInteractionStarted(PlayerTouchController playerRef, FollowerController followerRef)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("Pickup: PlayerTouchController or FollowerController missing.");
|
_playerRef = playerRef;
|
||||||
return;
|
FollowerController = followerRef;
|
||||||
}
|
}
|
||||||
float playerStopDistance = GameManager.Instance.PlayerStopDistance;
|
|
||||||
float followerPickupDelay = GameManager.Instance.FollowerPickupDelay;
|
protected virtual void OnCharacterArrived()
|
||||||
// --- Local event/coroutine handlers ---
|
|
||||||
void OnPlayerArrived()
|
|
||||||
{
|
{
|
||||||
playerController.OnArrivedAtTarget -= OnPlayerArrived;
|
var combinationResult = FollowerController.TryCombineItems(this, out var combinationResultItem);
|
||||||
playerController.OnMoveToCancelled -= OnPlayerMoveCancelled;
|
if (combinationResultItem != null)
|
||||||
pickupInProgress = true;
|
|
||||||
StartCoroutine(DispatchFollower());
|
|
||||||
}
|
|
||||||
void OnPlayerMoveCancelled()
|
|
||||||
{
|
|
||||||
playerController.OnArrivedAtTarget -= OnPlayerArrived;
|
|
||||||
playerController.OnMoveToCancelled -= OnPlayerMoveCancelled;
|
|
||||||
pickupInProgress = false;
|
|
||||||
}
|
|
||||||
System.Collections.IEnumerator DispatchFollower()
|
|
||||||
{
|
|
||||||
yield return new WaitForSeconds(followerPickupDelay);
|
|
||||||
followerController.OnPickupArrived += OnFollowerArrived;
|
|
||||||
followerController.OnPickupReturned += OnFollowerReturned;
|
|
||||||
followerController.GoToPointAndReturn(transform.position, playerObj.transform);
|
|
||||||
}
|
|
||||||
void OnFollowerArrived()
|
|
||||||
{
|
|
||||||
followerController.OnPickupArrived -= OnFollowerArrived;
|
|
||||||
bool interactionSuccess = true;
|
|
||||||
if (interactable != null)
|
|
||||||
{
|
{
|
||||||
interactionSuccess = interactable.OnFollowerArrived(followerController);
|
Interactable.BroadcastInteractionComplete(true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
followerController.SetInteractionResult(interactionSuccess);
|
|
||||||
}
|
FollowerController?.TryPickupItem(gameObject, itemData);
|
||||||
void OnFollowerReturned()
|
Interactable.BroadcastInteractionComplete(combinationResult == FollowerController.CombinationResult.NotApplicable);
|
||||||
{
|
|
||||||
followerController.OnPickupReturned -= OnFollowerReturned;
|
|
||||||
pickupInProgress = false;
|
|
||||||
}
|
|
||||||
playerController.OnArrivedAtTarget += OnPlayerArrived;
|
|
||||||
playerController.OnMoveToCancelled += OnPlayerMoveCancelled;
|
|
||||||
Vector3 stopPoint = transform.position + (playerObj.transform.position - transform.position).normalized * playerStopDistance;
|
|
||||||
float distToPickup = Vector2.Distance(new Vector2(playerObj.transform.position.x, playerObj.transform.position.y), new Vector2(transform.position.x, transform.position.y));
|
|
||||||
float dist = Vector2.Distance(new Vector2(playerObj.transform.position.x, playerObj.transform.position.y), new Vector2(stopPoint.x, stopPoint.y));
|
|
||||||
if (distToPickup <= playerStopDistance || dist <= 0.2f)
|
|
||||||
{
|
|
||||||
OnPlayerArrived();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
playerController.MoveToAndNotify(stopPoint);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
|
||||||
/// Handles completion of the interaction (e.g., after pickup is done).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="success">Whether the interaction was successful.</param>
|
|
||||||
private void OnInteractionComplete(bool success)
|
|
||||||
{
|
|
||||||
if (!success) return;
|
|
||||||
// Optionally, add logic to disable the pickup or provide feedback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction requirement that checks if the follower is holding a specific required item.
|
|
||||||
/// </summary>
|
|
||||||
[RequireComponent(typeof(Interactable))]
|
|
||||||
public class RequiresItemBehavior : InteractionRequirementBase
|
|
||||||
{
|
|
||||||
[Header("Required Item")]
|
|
||||||
public PickupItemData requiredItem;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to interact, succeeds only if the follower is holding the required item.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="follower">The follower attempting the interaction.</param>
|
|
||||||
/// <returns>True if the interaction was successful, false otherwise.</returns>
|
|
||||||
public override bool TryInteract(FollowerController follower)
|
|
||||||
{
|
|
||||||
var heldItem = follower.CurrentlyHeldItem;
|
|
||||||
if (heldItem == requiredItem)
|
|
||||||
{
|
|
||||||
OnSuccess?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string requiredName = requiredItem != null ? requiredItem.itemName : "required item";
|
|
||||||
if (heldItem == null)
|
|
||||||
{
|
|
||||||
DebugUIMessage.Show($"You need {requiredName} to interact.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string heldName = heldItem.itemName ?? "an item";
|
|
||||||
DebugUIMessage.Show($"You need {requiredName}, but you are holding {heldName}.");
|
|
||||||
}
|
|
||||||
OnFailure?.Invoke();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 31103d67032c44a9b95ec014babe2c62
|
|
||||||
timeCreated: 1756981777
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction requirement that allows slotting, swapping, or picking up items in a slot.
|
|
||||||
/// </summary>
|
|
||||||
[RequireComponent(typeof(Interactable))]
|
|
||||||
[RequireComponent(typeof(Pickup))]
|
|
||||||
public class SlotItemBehavior : InteractionRequirementBase
|
|
||||||
{
|
|
||||||
[Header("Slot State")]
|
|
||||||
/// <summary>
|
|
||||||
/// The item currently slotted in this slot.
|
|
||||||
/// </summary>
|
|
||||||
public PickupItemData currentlySlottedItem;
|
|
||||||
/// <summary>
|
|
||||||
/// The renderer for the slotted item's sprite.
|
|
||||||
/// </summary>
|
|
||||||
public SpriteRenderer slottedItemRenderer;
|
|
||||||
|
|
||||||
private GameObject _cachedSlottedObject = null;
|
|
||||||
|
|
||||||
// Helper for slotting an object, with option to skip destruction (for swap)
|
|
||||||
private void SetSlottedObject(GameObject obj)
|
|
||||||
{
|
|
||||||
_cachedSlottedObject = obj;
|
|
||||||
if (_cachedSlottedObject != null)
|
|
||||||
{
|
|
||||||
_cachedSlottedObject.SetActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RemoveSlottedObject()
|
|
||||||
{
|
|
||||||
if (_cachedSlottedObject != null)
|
|
||||||
{
|
|
||||||
Destroy(_cachedSlottedObject);
|
|
||||||
_cachedSlottedObject = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CacheSlottedObject(GameObject obj)
|
|
||||||
{
|
|
||||||
// Only destroy if not swapping
|
|
||||||
RemoveSlottedObject();
|
|
||||||
SetSlottedObject(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RestoreSlottedObject(Vector3 position)
|
|
||||||
{
|
|
||||||
if (_cachedSlottedObject != null)
|
|
||||||
{
|
|
||||||
_cachedSlottedObject.transform.position = position;
|
|
||||||
_cachedSlottedObject.transform.SetParent(null);
|
|
||||||
_cachedSlottedObject.SetActive(true);
|
|
||||||
_cachedSlottedObject = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to interact with the slot, handling slotting, swapping, or picking up items.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="follower">The follower attempting the interaction.</param>
|
|
||||||
/// <returns>True if the interaction was successful, false otherwise.</returns>
|
|
||||||
public override bool TryInteract(FollowerController follower)
|
|
||||||
{
|
|
||||||
var heldItem = follower.CurrentlyHeldItem;
|
|
||||||
var heldObj = follower.GetHeldPickupObject();
|
|
||||||
var pickup = GetComponent<Pickup>();
|
|
||||||
var slotItem = pickup != null ? pickup.itemData : null;
|
|
||||||
var config = GameManager.Instance.GetSlotItemConfig(slotItem);
|
|
||||||
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
|
||||||
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
|
|
||||||
|
|
||||||
// CASE 1: No held item, slot has item -> pick up slotted item
|
|
||||||
if (heldItem == null && _cachedSlottedObject != null)
|
|
||||||
{
|
|
||||||
follower.SetHeldItemFromObject(_cachedSlottedObject);
|
|
||||||
RemoveSlottedObject();
|
|
||||||
currentlySlottedItem = null;
|
|
||||||
UpdateSlottedSprite();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// CASE 2: Held item, slot has item -> swap
|
|
||||||
if (heldItem != null && _cachedSlottedObject != null)
|
|
||||||
{
|
|
||||||
var followerHeldObj = heldObj;
|
|
||||||
var followerHeldItem = heldItem;
|
|
||||||
var slotObj = _cachedSlottedObject;
|
|
||||||
var slotItemData = currentlySlottedItem;
|
|
||||||
|
|
||||||
// 1. Slot the follower's held object (do NOT destroy the old one)
|
|
||||||
SetSlottedObject(followerHeldObj);
|
|
||||||
currentlySlottedItem = followerHeldItem;
|
|
||||||
UpdateSlottedSprite();
|
|
||||||
|
|
||||||
// 2. Give the slot's object to the follower
|
|
||||||
follower.SetHeldItemFromObject(slotObj);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// CASE 3: Held item, slot empty -> slot the held item
|
|
||||||
if (heldItem != null && _cachedSlottedObject == null)
|
|
||||||
{
|
|
||||||
if (forbidden.Contains(heldItem))
|
|
||||||
{
|
|
||||||
DebugUIMessage.Show("Can't place that here.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
CacheSlottedObject(heldObj);
|
|
||||||
currentlySlottedItem = heldItem;
|
|
||||||
UpdateSlottedSprite();
|
|
||||||
follower.ClearHeldItem();
|
|
||||||
if (allowed.Contains(heldItem))
|
|
||||||
{
|
|
||||||
OnSuccess?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugUIMessage.Show("I'm not sure this works.");
|
|
||||||
OnFailure?.Invoke();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// CASE 4: No held item, slot empty -> show warning
|
|
||||||
if (heldItem == null && _cachedSlottedObject == null)
|
|
||||||
{
|
|
||||||
DebugUIMessage.Show("This requires an item.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the sprite and scale for the currently slotted item.
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateSlottedSprite()
|
|
||||||
{
|
|
||||||
if (slottedItemRenderer != null && currentlySlottedItem != null && currentlySlottedItem.mapSprite != null)
|
|
||||||
{
|
|
||||||
slottedItemRenderer.sprite = currentlySlottedItem.mapSprite;
|
|
||||||
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
|
|
||||||
float desiredHeight = GameManager.Instance.HeldIconDisplayHeight;
|
|
||||||
var sprite = currentlySlottedItem.mapSprite;
|
|
||||||
float spriteHeight = sprite.bounds.size.y;
|
|
||||||
float spriteWidth = sprite.bounds.size.x;
|
|
||||||
Vector3 parentScale = slottedItemRenderer.transform.parent != null
|
|
||||||
? slottedItemRenderer.transform.parent.localScale
|
|
||||||
: Vector3.one;
|
|
||||||
if (spriteHeight > 0f)
|
|
||||||
{
|
|
||||||
float uniformScale = desiredHeight / spriteHeight;
|
|
||||||
float scale = uniformScale / Mathf.Max(parentScale.x, parentScale.y);
|
|
||||||
slottedItemRenderer.transform.localScale = new Vector3(scale, scale, 1f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (slottedItemRenderer != null)
|
|
||||||
{
|
|
||||||
slottedItemRenderer.sprite = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Input;
|
||||||
|
using Interactions;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,7 +28,7 @@ public class LevelSwitch : MonoBehaviour
|
|||||||
_interactable = GetComponent<Interactable>();
|
_interactable = GetComponent<Interactable>();
|
||||||
if (_interactable != null)
|
if (_interactable != null)
|
||||||
{
|
{
|
||||||
_interactable.StartedInteraction += OnStartedInteraction;
|
_interactable.characterArrived.AddListener(OnCharacterArrived);
|
||||||
}
|
}
|
||||||
ApplySwitchData();
|
ApplySwitchData();
|
||||||
}
|
}
|
||||||
@@ -38,7 +40,7 @@ public class LevelSwitch : MonoBehaviour
|
|||||||
{
|
{
|
||||||
if (_interactable != null)
|
if (_interactable != null)
|
||||||
{
|
{
|
||||||
_interactable.StartedInteraction -= OnStartedInteraction;
|
_interactable.characterArrived.RemoveListener(OnCharacterArrived);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ public class LevelSwitch : MonoBehaviour
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles the start of an interaction (shows confirmation menu and switches the level if confirmed).
|
/// Handles the start of an interaction (shows confirmation menu and switches the level if confirmed).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnStartedInteraction()
|
private void OnCharacterArrived()
|
||||||
{
|
{
|
||||||
if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName) || !_isActive)
|
if (switchData == null || string.IsNullOrEmpty(switchData.targetLevelSceneName) || !_isActive)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using UnityEngine;
|
using Interactions;
|
||||||
|
using UnityEngine;
|
||||||
using Pathfinding;
|
using Pathfinding;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using Utils;
|
using Utils;
|
||||||
@@ -6,7 +7,7 @@ using Utils;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controls the follower character, including following the player, handling pickups, and managing held items.
|
/// Controls the follower character, including following the player, handling pickups, and managing held items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FollowerController : MonoBehaviour
|
public class FollowerController: MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Follower Settings")]
|
[Header("Follower Settings")]
|
||||||
public bool debugDrawTarget = true;
|
public bool debugDrawTarget = true;
|
||||||
@@ -29,10 +30,13 @@ public class FollowerController : MonoBehaviour
|
|||||||
private float _currentSpeed = 0f;
|
private float _currentSpeed = 0f;
|
||||||
private Animator _animator;
|
private Animator _animator;
|
||||||
private Transform _artTransform;
|
private Transform _artTransform;
|
||||||
private SpriteRenderer spriteRenderer;
|
private SpriteRenderer _spriteRenderer;
|
||||||
|
|
||||||
|
private PickupItemData _currentlyHeldItemData;
|
||||||
|
public PickupItemData CurrentlyHeldItemData => _currentlyHeldItemData;
|
||||||
|
private GameObject _cachedPickupObject = null;
|
||||||
|
public bool justCombined = false;
|
||||||
|
|
||||||
private PickupItemData _currentlyHeldItem;
|
|
||||||
public PickupItemData CurrentlyHeldItem => _currentlyHeldItem;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Renderer for the held item icon.
|
/// Renderer for the held item icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -54,27 +58,9 @@ public class FollowerController : MonoBehaviour
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event FollowerPickupHandler OnPickupReturned;
|
public event FollowerPickupHandler OnPickupReturned;
|
||||||
private Coroutine _pickupCoroutine;
|
private Coroutine _pickupCoroutine;
|
||||||
|
|
||||||
private bool _lastInteractionSuccess = true;
|
private bool _lastInteractionSuccess = true;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cache for the currently picked-up GameObject (hidden while held).
|
|
||||||
/// </summary>
|
|
||||||
private GameObject _cachedPickupObject = null;
|
|
||||||
public bool justCombined = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Caches the given pickup object as the currently held item, hides it, and parents it to the follower.
|
|
||||||
/// </summary>
|
|
||||||
public void CacheHeldPickupObject(GameObject obj)
|
|
||||||
{
|
|
||||||
// Do not destroy the previous object; just replace and hide
|
|
||||||
_cachedPickupObject = obj;
|
|
||||||
if (_cachedPickupObject != null)
|
|
||||||
{
|
|
||||||
_cachedPickupObject.SetActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
@@ -84,12 +70,12 @@ public class FollowerController : MonoBehaviour
|
|||||||
if (_artTransform != null)
|
if (_artTransform != null)
|
||||||
{
|
{
|
||||||
_animator = _artTransform.GetComponent<Animator>();
|
_animator = _artTransform.GetComponent<Animator>();
|
||||||
spriteRenderer = _artTransform.GetComponent<SpriteRenderer>();
|
_spriteRenderer = _artTransform.GetComponent<SpriteRenderer>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_animator = GetComponentInChildren<Animator>(); // fallback
|
_animator = GetComponentInChildren<Animator>(); // fallback
|
||||||
spriteRenderer = GetComponentInChildren<SpriteRenderer>();
|
_spriteRenderer = GetComponentInChildren<SpriteRenderer>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,38 +94,7 @@ public class FollowerController : MonoBehaviour
|
|||||||
{
|
{
|
||||||
FindPlayerReference();
|
FindPlayerReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateFollowTarget()
|
|
||||||
{
|
|
||||||
if (_playerTransform == null)
|
|
||||||
{
|
|
||||||
FindPlayerReference();
|
|
||||||
if (_playerTransform == null)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_isManualFollowing)
|
|
||||||
{
|
|
||||||
Vector3 playerPos = _playerTransform.position;
|
|
||||||
Vector3 moveDir = Vector3.zero;
|
|
||||||
if (_playerAIPath != null && _playerAIPath.velocity.magnitude > 0.01f)
|
|
||||||
{
|
|
||||||
moveDir = _playerAIPath.velocity.normalized;
|
|
||||||
_lastMoveDir = moveDir;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
moveDir = _lastMoveDir;
|
|
||||||
}
|
|
||||||
// Use GameSettings for followDistance
|
|
||||||
_targetPoint = playerPos - moveDir * GameManager.Instance.FollowDistance;
|
|
||||||
_targetPoint.z = 0;
|
|
||||||
if (_aiPath != null)
|
|
||||||
{
|
|
||||||
_aiPath.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
if (_playerTransform == null)
|
if (_playerTransform == null)
|
||||||
@@ -185,12 +140,12 @@ public class FollowerController : MonoBehaviour
|
|||||||
}
|
}
|
||||||
Vector3 dir = (_targetPoint - transform.position).normalized;
|
Vector3 dir = (_targetPoint - transform.position).normalized;
|
||||||
// Sprite flipping based on movement direction
|
// Sprite flipping based on movement direction
|
||||||
if (spriteRenderer != null && dir.sqrMagnitude > 0.001f)
|
if (_spriteRenderer != null && dir.sqrMagnitude > 0.001f)
|
||||||
{
|
{
|
||||||
if (dir.x > 0.01f)
|
if (dir.x > 0.01f)
|
||||||
spriteRenderer.flipX = false;
|
_spriteRenderer.flipX = false;
|
||||||
else if (dir.x < -0.01f)
|
else if (dir.x < -0.01f)
|
||||||
spriteRenderer.flipX = true;
|
_spriteRenderer.flipX = true;
|
||||||
}
|
}
|
||||||
transform.position += dir * _currentSpeed * Time.deltaTime;
|
transform.position += dir * _currentSpeed * Time.deltaTime;
|
||||||
}
|
}
|
||||||
@@ -214,12 +169,12 @@ public class FollowerController : MonoBehaviour
|
|||||||
{
|
{
|
||||||
normalizedSpeed = _aiPath.velocity.magnitude / _followerMaxSpeed;
|
normalizedSpeed = _aiPath.velocity.magnitude / _followerMaxSpeed;
|
||||||
// Sprite flipping for pathfinding mode
|
// Sprite flipping for pathfinding mode
|
||||||
if (spriteRenderer != null && _aiPath.velocity.sqrMagnitude > 0.001f)
|
if (_spriteRenderer != null && _aiPath.velocity.sqrMagnitude > 0.001f)
|
||||||
{
|
{
|
||||||
if (_aiPath.velocity.x > 0.01f)
|
if (_aiPath.velocity.x > 0.01f)
|
||||||
spriteRenderer.flipX = false;
|
_spriteRenderer.flipX = false;
|
||||||
else if (_aiPath.velocity.x < -0.01f)
|
else if (_aiPath.velocity.x < -0.01f)
|
||||||
spriteRenderer.flipX = true;
|
_spriteRenderer.flipX = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_animator.SetFloat("Speed", Mathf.Clamp01(normalizedSpeed));
|
_animator.SetFloat("Speed", Mathf.Clamp01(normalizedSpeed));
|
||||||
@@ -246,7 +201,44 @@ public class FollowerController : MonoBehaviour
|
|||||||
_playerAIPath = null;
|
_playerAIPath = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Movement
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the follower's target point to follow the player at a specified distance,
|
||||||
|
/// using the player's current movement direction if available. Disables pathfinding
|
||||||
|
/// when in manual following mode.
|
||||||
|
/// </summary>
|
||||||
|
void UpdateFollowTarget()
|
||||||
|
{
|
||||||
|
if (_playerTransform == null)
|
||||||
|
{
|
||||||
|
FindPlayerReference();
|
||||||
|
if (_playerTransform == null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_isManualFollowing)
|
||||||
|
{
|
||||||
|
Vector3 playerPos = _playerTransform.position;
|
||||||
|
Vector3 moveDir = Vector3.zero;
|
||||||
|
if (_playerAIPath != null && _playerAIPath.velocity.magnitude > 0.01f)
|
||||||
|
{
|
||||||
|
moveDir = _playerAIPath.velocity.normalized;
|
||||||
|
_lastMoveDir = moveDir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
moveDir = _lastMoveDir;
|
||||||
|
}
|
||||||
|
// Use GameSettings for followDistance
|
||||||
|
_targetPoint = playerPos - moveDir * GameManager.Instance.FollowDistance;
|
||||||
|
_targetPoint.z = 0;
|
||||||
|
if (_aiPath != null)
|
||||||
|
{
|
||||||
|
_aiPath.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Command follower to go to a specific point (pathfinding mode)
|
// Command follower to go to a specific point (pathfinding mode)
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Command follower to go to a specific point (pathfinding mode).
|
/// Command follower to go to a specific point (pathfinding mode).
|
||||||
@@ -277,77 +269,7 @@ public class FollowerController : MonoBehaviour
|
|||||||
_aiPath.maxSpeed = _followerMaxSpeed;
|
_aiPath.maxSpeed = _followerMaxSpeed;
|
||||||
_pickupCoroutine = StartCoroutine(PickupSequence(itemPosition, playerTransform));
|
_pickupCoroutine = StartCoroutine(PickupSequence(itemPosition, playerTransform));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the item held by the follower, copying all visual properties from the Pickup's SpriteRenderer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemData">The item data to set.</param>
|
|
||||||
/// <param name="pickupRenderer">The SpriteRenderer from the Pickup to copy appearance from.</param>
|
|
||||||
public void SetHeldItem(PickupItemData itemData, SpriteRenderer pickupRenderer = null)
|
|
||||||
{
|
|
||||||
_currentlyHeldItem = itemData;
|
|
||||||
if (heldObjectRenderer != null)
|
|
||||||
{
|
|
||||||
if (_currentlyHeldItem != null && pickupRenderer != null)
|
|
||||||
{
|
|
||||||
AppleHillsUtils.CopySpriteRendererProperties(pickupRenderer, heldObjectRenderer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
heldObjectRenderer.sprite = null;
|
|
||||||
heldObjectRenderer.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the result of the last interaction (success or failure).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="success">True if the last interaction was successful, false otherwise.</param>
|
|
||||||
public void SetInteractionResult(bool success)
|
|
||||||
{
|
|
||||||
_lastInteractionSuccess = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GameObject GetHeldPickupObject()
|
|
||||||
{
|
|
||||||
return _cachedPickupObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetHeldItemFromObject(GameObject obj)
|
|
||||||
{
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
ClearHeldItem();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var pickup = obj.GetComponent<Pickup>();
|
|
||||||
if (pickup != null)
|
|
||||||
{
|
|
||||||
SetHeldItem(pickup.itemData, pickup.iconRenderer);
|
|
||||||
CacheHeldPickupObject(obj);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ClearHeldItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearHeldItem()
|
|
||||||
{
|
|
||||||
if (_cachedPickupObject != null)
|
|
||||||
{
|
|
||||||
// Destroy(_cachedPickupObject);
|
|
||||||
_cachedPickupObject = null;
|
|
||||||
}
|
|
||||||
_currentlyHeldItem = null;
|
|
||||||
if (heldObjectRenderer != null)
|
|
||||||
{
|
|
||||||
heldObjectRenderer.sprite = null;
|
|
||||||
heldObjectRenderer.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private System.Collections.IEnumerator PickupSequence(Vector2 itemPosition, Transform playerTransform)
|
private System.Collections.IEnumerator PickupSequence(Vector2 itemPosition, Transform playerTransform)
|
||||||
{
|
{
|
||||||
_isManualFollowing = false;
|
_isManualFollowing = false;
|
||||||
@@ -364,42 +286,7 @@ public class FollowerController : MonoBehaviour
|
|||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
OnPickupArrived?.Invoke();
|
OnPickupArrived?.Invoke();
|
||||||
// Only perform pickup/swap logic if interaction succeeded
|
|
||||||
if (_lastInteractionSuccess && heldObjectRenderer != null)
|
|
||||||
{
|
|
||||||
Collider2D[] hits = Physics2D.OverlapCircleAll(itemPosition, 0.2f);
|
|
||||||
foreach (var hit in hits)
|
|
||||||
{
|
|
||||||
var pickup = hit.GetComponent<Pickup>();
|
|
||||||
if (pickup != null)
|
|
||||||
{
|
|
||||||
var slotBehavior = pickup.GetComponent<SlotItemBehavior>();
|
|
||||||
if (slotBehavior != null)
|
|
||||||
{
|
|
||||||
// Slot item: do not destroy or swap, just return to player
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (justCombined)
|
|
||||||
{
|
|
||||||
GameObject.Destroy(pickup.gameObject);
|
|
||||||
justCombined = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Swap logic: if holding an item, drop it here
|
|
||||||
if (_currentlyHeldItem != null && _cachedPickupObject != null)
|
|
||||||
{
|
|
||||||
// Drop the cached object at the pickup's position
|
|
||||||
_cachedPickupObject.transform.position = pickup.transform.position;
|
|
||||||
_cachedPickupObject.transform.SetParent(null);
|
|
||||||
_cachedPickupObject.SetActive(true);
|
|
||||||
_cachedPickupObject = null;
|
|
||||||
}
|
|
||||||
SetHeldItem(pickup.itemData, pickup.iconRenderer);
|
|
||||||
CacheHeldPickupObject(pickup.gameObject);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Wait briefly, then return to player
|
// Wait briefly, then return to player
|
||||||
yield return new WaitForSeconds(0.2f);
|
yield return new WaitForSeconds(0.2f);
|
||||||
if (_aiPath != null && playerTransform != null)
|
if (_aiPath != null && playerTransform != null)
|
||||||
@@ -424,28 +311,134 @@ public class FollowerController : MonoBehaviour
|
|||||||
_aiPath.enabled = false;
|
_aiPath.enabled = false;
|
||||||
_pickupCoroutine = null;
|
_pickupCoroutine = null;
|
||||||
}
|
}
|
||||||
|
#endregion Movement
|
||||||
/// <summary>
|
|
||||||
/// Drop the held item at the specified position, unparenting and activating it.
|
#region ItemInteractions
|
||||||
/// </summary>
|
public void TryPickupItem(GameObject itemObject, PickupItemData itemData)
|
||||||
/// <param name="position">The world position to drop the item at.</param>
|
|
||||||
public void DropHeldItemAt(Vector3 position)
|
|
||||||
{
|
{
|
||||||
if (_cachedPickupObject != null)
|
if (_currentlyHeldItemData != null && _cachedPickupObject != null)
|
||||||
{
|
{
|
||||||
_cachedPickupObject.transform.position = position;
|
// Drop the currently held item at the current position
|
||||||
_cachedPickupObject.transform.SetParent(null);
|
DropHeldItemAt(transform.position);
|
||||||
_cachedPickupObject.SetActive(true);
|
}
|
||||||
_cachedPickupObject = null;
|
// Pick up the new item
|
||||||
_currentlyHeldItem = null;
|
SetHeldItem(itemData, itemObject.GetComponent<SpriteRenderer>());
|
||||||
if (heldObjectRenderer != null)
|
_cachedPickupObject = itemObject;
|
||||||
|
_cachedPickupObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CombinationResult
|
||||||
|
{
|
||||||
|
Successful,
|
||||||
|
Unsuccessful,
|
||||||
|
NotApplicable
|
||||||
|
}
|
||||||
|
|
||||||
|
public CombinationResult TryCombineItems(Pickup pickupA, out GameObject newItem)
|
||||||
|
{
|
||||||
|
newItem = null;
|
||||||
|
if (_cachedPickupObject == null)
|
||||||
|
{
|
||||||
|
return CombinationResult.NotApplicable;
|
||||||
|
}
|
||||||
|
Pickup pickupB = _cachedPickupObject.GetComponent<Pickup>();
|
||||||
|
if (pickupA == null || pickupB == null)
|
||||||
|
{
|
||||||
|
return CombinationResult.NotApplicable;
|
||||||
|
}
|
||||||
|
var rule = GameManager.Instance.GetCombinationRule(pickupA.itemData, pickupB.itemData);
|
||||||
|
Vector3 spawnPos = pickupA.gameObject.transform.position;
|
||||||
|
if (rule != null && rule.resultPrefab != null)
|
||||||
|
{
|
||||||
|
newItem = Instantiate(rule.resultPrefab, spawnPos, Quaternion.identity);
|
||||||
|
PickupItemData itemData = newItem.GetComponent<Pickup>().itemData;
|
||||||
|
Destroy(pickupA.gameObject);
|
||||||
|
Destroy(pickupB.gameObject);
|
||||||
|
TryPickupItem(newItem,itemData);
|
||||||
|
return CombinationResult.Successful;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no combination found, return Unsuccessful
|
||||||
|
return CombinationResult.Unsuccessful;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the item held by the follower, copying all visual properties from the Pickup's SpriteRenderer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemData">The item data to set.</param>
|
||||||
|
/// <param name="pickupRenderer">The SpriteRenderer from the Pickup to copy appearance from.</param>
|
||||||
|
public void SetHeldItem(PickupItemData itemData, SpriteRenderer pickupRenderer = null)
|
||||||
|
{
|
||||||
|
_currentlyHeldItemData = itemData;
|
||||||
|
if (heldObjectRenderer != null)
|
||||||
|
{
|
||||||
|
if (_currentlyHeldItemData != null && pickupRenderer != null)
|
||||||
|
{
|
||||||
|
AppleHillsUtils.CopySpriteRendererProperties(pickupRenderer, heldObjectRenderer);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
heldObjectRenderer.sprite = null;
|
heldObjectRenderer.sprite = null;
|
||||||
heldObjectRenderer.enabled = false;
|
heldObjectRenderer.enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GameObject GetHeldPickupObject()
|
||||||
|
{
|
||||||
|
return _cachedPickupObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetHeldItemFromObject(GameObject obj)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
ClearHeldItem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pickup = obj.GetComponent<Pickup>();
|
||||||
|
if (pickup != null)
|
||||||
|
{
|
||||||
|
SetHeldItem(pickup.itemData, pickup.iconRenderer);
|
||||||
|
_cachedPickupObject = obj;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClearHeldItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearHeldItem()
|
||||||
|
{
|
||||||
|
_cachedPickupObject = null;
|
||||||
|
_currentlyHeldItemData = null;
|
||||||
|
if (heldObjectRenderer != null)
|
||||||
|
{
|
||||||
|
heldObjectRenderer.sprite = null;
|
||||||
|
heldObjectRenderer.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropItem(FollowerController follower, Vector3 position)
|
||||||
|
{
|
||||||
|
var item = follower.GetHeldPickupObject();
|
||||||
|
if (item == null) return;
|
||||||
|
item.transform.position = position;
|
||||||
|
item.transform.SetParent(null);
|
||||||
|
item.SetActive(true);
|
||||||
|
follower.ClearHeldItem();
|
||||||
|
// Optionally: fire event, update UI, etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropHeldItemAt(Vector3 position)
|
||||||
|
{
|
||||||
|
DropItem(this, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion ItemInteractions
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
void OnDrawGizmos()
|
void OnDrawGizmos()
|
||||||
{
|
{
|
||||||
if (debugDrawTarget && Application.isPlaying)
|
if (debugDrawTarget && Application.isPlaying)
|
||||||
@@ -456,6 +449,5 @@ public class FollowerController : MonoBehaviour
|
|||||||
Gizmos.DrawLine(transform.position, _targetPoint);
|
Gizmos.DrawLine(transform.position, _targetPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,93 +1,97 @@
|
|||||||
|
using Input;
|
||||||
|
using Interactions;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
/// <summary>
|
namespace PuzzleS
|
||||||
/// Manages the state and interactions for a single puzzle step, including unlock/lock logic and event handling.
|
|
||||||
/// </summary>
|
|
||||||
[RequireComponent(typeof(Interactable))]
|
|
||||||
public class ObjectiveStepBehaviour : MonoBehaviour
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The data object representing this puzzle step.
|
/// Manages the state and interactions for a single puzzle step, including unlock/lock logic and event handling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PuzzleStepSO stepData;
|
[RequireComponent(typeof(Interactable))]
|
||||||
private Interactable interactable;
|
public class ObjectiveStepBehaviour : MonoBehaviour
|
||||||
private bool isUnlocked = false;
|
|
||||||
|
|
||||||
void Awake()
|
|
||||||
{
|
{
|
||||||
interactable = GetComponent<Interactable>();
|
/// <summary>
|
||||||
}
|
/// The data object representing this puzzle step.
|
||||||
|
/// </summary>
|
||||||
|
public PuzzleStepSO stepData;
|
||||||
|
private Interactable _interactable;
|
||||||
|
private bool _isUnlocked = false;
|
||||||
|
|
||||||
void OnEnable()
|
void Awake()
|
||||||
{
|
|
||||||
if (interactable == null)
|
|
||||||
interactable = GetComponent<Interactable>();
|
|
||||||
if (interactable != null)
|
|
||||||
{
|
{
|
||||||
interactable.StartedInteraction += OnStartedInteraction;
|
_interactable = GetComponent<Interactable>();
|
||||||
interactable.InteractionComplete += OnInteractionComplete;
|
|
||||||
}
|
}
|
||||||
PuzzleManager.Instance?.RegisterStepBehaviour(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnDisable()
|
void OnEnable()
|
||||||
{
|
|
||||||
if (interactable != null)
|
|
||||||
{
|
{
|
||||||
interactable.StartedInteraction -= OnStartedInteraction;
|
if (_interactable == null)
|
||||||
interactable.InteractionComplete -= OnInteractionComplete;
|
_interactable = GetComponent<Interactable>();
|
||||||
|
if (_interactable != null)
|
||||||
|
{
|
||||||
|
_interactable.interactionStarted.AddListener(OnInteractionStarted);
|
||||||
|
_interactable.interactionComplete.AddListener(OnInteractionComplete);
|
||||||
|
}
|
||||||
|
PuzzleManager.Instance?.RegisterStepBehaviour(this);
|
||||||
}
|
}
|
||||||
PuzzleManager.Instance?.UnregisterStepBehaviour(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
void OnDestroy()
|
||||||
/// Unlocks this puzzle step, allowing interaction.
|
|
||||||
/// </summary>
|
|
||||||
public void UnlockStep()
|
|
||||||
{
|
|
||||||
isUnlocked = true;
|
|
||||||
Debug.Log($"[Puzzles] Step unlocked: {stepData?.stepId} on {gameObject.name}");
|
|
||||||
// Optionally, show visual feedback for unlocked state
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Locks this puzzle step, preventing interaction.
|
|
||||||
/// </summary>
|
|
||||||
public void LockStep()
|
|
||||||
{
|
|
||||||
isUnlocked = false;
|
|
||||||
Debug.Log($"[Puzzles] Step locked: {stepData?.stepId} on {gameObject.name}");
|
|
||||||
// Optionally, show visual feedback for locked state
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns whether this step is currently unlocked.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsStepUnlocked()
|
|
||||||
{
|
|
||||||
return isUnlocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the start of an interaction (can be used for visual feedback).
|
|
||||||
/// </summary>
|
|
||||||
private void OnStartedInteraction()
|
|
||||||
{
|
|
||||||
// Optionally handle started interaction (e.g. visual feedback)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles completion of the interaction, notifies PuzzleManager if successful and unlocked.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="success">Whether the interaction was successful.</param>
|
|
||||||
private void OnInteractionComplete(bool success)
|
|
||||||
{
|
|
||||||
if (!isUnlocked) return;
|
|
||||||
if (success)
|
|
||||||
{
|
{
|
||||||
Debug.Log($"[Puzzles] Step interacted: {stepData?.stepId} on {gameObject.name}");
|
if (_interactable != null)
|
||||||
PuzzleManager.Instance?.OnStepCompleted(stepData);
|
{
|
||||||
|
_interactable.interactionStarted.RemoveListener(OnInteractionStarted);
|
||||||
|
_interactable.interactionComplete.RemoveListener(OnInteractionComplete);
|
||||||
|
}
|
||||||
|
PuzzleManager.Instance?.UnregisterStepBehaviour(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unlocks this puzzle step, allowing interaction.
|
||||||
|
/// </summary>
|
||||||
|
public void UnlockStep()
|
||||||
|
{
|
||||||
|
_isUnlocked = true;
|
||||||
|
Debug.Log($"[Puzzles] Step unlocked: {stepData?.stepId} on {gameObject.name}");
|
||||||
|
// Optionally, show visual feedback for unlocked state
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Locks this puzzle step, preventing interaction.
|
||||||
|
/// </summary>
|
||||||
|
public void LockStep()
|
||||||
|
{
|
||||||
|
_isUnlocked = false;
|
||||||
|
Debug.Log($"[Puzzles] Step locked: {stepData?.stepId} on {gameObject.name}");
|
||||||
|
// Optionally, show visual feedback for locked state
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether this step is currently unlocked.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsStepUnlocked()
|
||||||
|
{
|
||||||
|
return _isUnlocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the start of an interaction (can be used for visual feedback).
|
||||||
|
/// </summary>
|
||||||
|
private void OnInteractionStarted(PlayerTouchController playerRef, FollowerController followerRef)
|
||||||
|
{
|
||||||
|
// Optionally handle started interaction (e.g. visual feedback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles completion of the interaction, notifies PuzzleManager if successful and unlocked.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="success">Whether the interaction was successful.</param>
|
||||||
|
private void OnInteractionComplete(bool success)
|
||||||
|
{
|
||||||
|
if (!_isUnlocked) return;
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Debug.Log($"[Puzzles] Step interacted: {stepData?.stepId} on {gameObject.name}");
|
||||||
|
PuzzleManager.Instance?.OnStepCompleted(stepData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using PuzzleS;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Manages puzzle step registration, dependency management, and step completion for the puzzle system.
|
/// Manages puzzle step registration, dependency management, and step completion for the puzzle system.
|
||||||
|
|||||||
Reference in New Issue
Block a user