Commit 9833ad6e authored by Mahmoud Aglan's avatar Mahmoud Aglan

kk

parent c468ac1e
......@@ -119,6 +119,83 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &248844674
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 248844676}
- component: {fileID: 248844675}
m_Layer: 0
m_Name: GameObject (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!114 &248844675
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 248844674}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f01ccea8ba624884b1d770a47d7e8a11, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::com.al_arcade.cs.CsPrefabBuilder
environmentPrefab: {fileID: 0}
cameraOverride: {fileID: 0}
cameraPosition: {x: 0, y: 4, z: -6}
cameraRotation: {x: 25, y: 0, z: 0}
cameraFOV: 60
cameraBgColor: {r: 0.11764706, g: 0.11764706, b: 0.23529412, a: 1}
directionalLightPrefab: {fileID: 0}
extraLightPrefabs: []
ambientColor: {r: 0.15686275, g: 0.16470589, b: 0.23529412, a: 1}
botPrefab: {fileID: 0}
botSpawnPosition: {x: 0, y: 0, z: 0}
wordCardPrefab: {fileID: 0}
canvasPrefab: {fileID: 0}
sfxCorrect: {fileID: 0}
sfxWrong: {fileID: 0}
sfxClick: {fileID: 0}
sfxVictory: {fileID: 0}
sfxDefeat: {fileID: 0}
sfxWhoosh: {fileID: 0}
sfxPop: {fileID: 0}
sfxSlam: {fileID: 0}
sfxCheer: {fileID: 0}
correctBurstParticle: {fileID: 0}
wrongBurstParticle: {fileID: 0}
confettiParticle: {fileID: 0}
sparksParticle: {fileID: 0}
starBurstParticle: {fileID: 0}
arabicFont: {fileID: 0}
buildType: scistreet
gradeId: 0
questionCount: 8
classCode:
useOfflineTestData: 0
--- !u!4 &248844676
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 248844674}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 6.36753, y: -0, z: 37.12262}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &330585543
GameObject:
m_ObjectHideFlags: 0
......@@ -532,3 +609,4 @@ SceneRoots:
- {fileID: 410087041}
- {fileID: 832575519}
- {fileID: 1440871591}
- {fileID: 248844676}
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using DG.Tweening;
using TMPro;
namespace com.al_arcade.cs
{
using shared;
[AddComponentMenu("Science Street/CS Prefab Builder")]
public class CsPrefabBuilder : MonoBehaviour
{
// ════════════════════════════════════════════════════════════
// SCENE
// ════════════════════════════════════════════════════════════
[Header("Scene Environment")]
[Tooltip("Your full environment prefab (ground, platform, decorations, etc). Spawned at origin.")]
[SerializeField] private GameObject environmentPrefab;
[Header("Camera")]
[Tooltip("Leave null to use Camera.main with default settings.")]
[SerializeField] private Camera cameraOverride;
[SerializeField] private Vector3 cameraPosition = new Vector3(0, 4f, -6f);
[SerializeField] private Vector3 cameraRotation = new Vector3(25, 0, 0);
[SerializeField] private float cameraFOV = 60f;
[SerializeField] private Color cameraBgColor = new Color32(30, 30, 60, 255);
// ════════════════════════════════════════════════════════════
// LIGHTING
// ════════════════════════════════════════════════════════════
[Header("Lighting (leave null to skip)")]
[Tooltip("Drag in your own directional light prefab, or leave null to auto-create.")]
[SerializeField] private GameObject directionalLightPrefab;
[SerializeField] private GameObject[] extraLightPrefabs;
[SerializeField] private Color ambientColor = new Color32(40, 42, 60, 255);
// ════════════════════════════════════════════════════════════
// BOT
// ════════════════════════════════════════════════════════════
[Header("Bot")]
[Tooltip("Your bot prefab. MUST have CsBotController attached.\n" +
"If null, a procedural bot is created.")]
[SerializeField] private GameObject botPrefab;
[SerializeField] private Vector3 botSpawnPosition = Vector3.zero;
// ════════════════════════════════════════════════════════════
// WORD CARD (optional override)
// ════════════════════════════════════════════════════════════
[Header("Word Card (optional)")]
[Tooltip("A prefab for the word card. MUST have CsWordButton.\n" +
"If null, the default procedural card is used.")]
[SerializeField] private GameObject wordCardPrefab;
// ════════════════════════════════════════════════════════════
// UI
// ════════════════════════════════════════════════════════════
[Header("UI Canvas")]
[Tooltip("Your Canvas prefab. MUST have CsUIManager with ALL internal " +
"references wired in the inspector.\n" +
"If null, a procedural UI is created.")]
[SerializeField] private GameObject canvasPrefab;
// ════════════════════════════════════════════════════════════
// AUDIO
// ════════════════════════════════════════════════════════════
[Header("Audio — SFX Clips (all optional)")]
[SerializeField] private AudioClip sfxCorrect;
[SerializeField] private AudioClip sfxWrong;
[SerializeField] private AudioClip sfxClick;
[SerializeField] private AudioClip sfxVictory;
[SerializeField] private AudioClip sfxDefeat;
[SerializeField] private AudioClip sfxWhoosh;
[SerializeField] private AudioClip sfxPop;
[SerializeField] private AudioClip sfxSlam;
[SerializeField] private AudioClip sfxCheer;
// ════════════════════════════════════════════════════════════
// PARTICLES
// ════════════════════════════════════════════════════════════
[Header("Particles (all optional)")]
[SerializeField] private ParticleSystem correctBurstParticle;
[SerializeField] private ParticleSystem wrongBurstParticle;
[SerializeField] private ParticleSystem confettiParticle;
[SerializeField] private ParticleSystem sparksParticle;
[SerializeField] private ParticleSystem starBurstParticle;
// ════════════════════════════════════════════════════════════
// FONT
// ════════════════════════════════════════════════════════════
[Header("Arabic Font")]
[SerializeField] private TMP_FontAsset arabicFont;
// ════════════════════════════════════════════════════════════
// GAME SETTINGS
// ════════════════════════════════════════════════════════════
[Header("Game Settings")]
[SerializeField] private string buildType = "scistreet";
[SerializeField] private int gradeId = 0;
[SerializeField] private int questionCount = 8;
[SerializeField] private string classCode = "";
[Header("Debug")]
[SerializeField] private bool useOfflineTestData = false;
// ════════════════════════════════════════════════════════════
// RUNTIME REFS
// ════════════════════════════════════════════════════════════
private CsGameManager _gm;
private CsBotController _bot;
private CsUIManager _uiManager;
// ════════════════════════════════════════════════════════════
// STARTUP
// ════════════════════════════════════════════════════════════
private void Start()
{
DOTween.Init();
if (arabicFont != null) SSFontManager.Font = arabicFont;
StartCoroutine(BuildEverything());
}
private IEnumerator BuildEverything()
{
Debug.Log("═══ CS Prefab Builder — Starting ═══");
// ── EventSystem ──────────────────────────────────────
if (FindObjectOfType<EventSystem>() == null)
{
var es = new GameObject("EventSystem");
es.AddComponent<EventSystem>();
es.AddComponent<StandaloneInputModule>();
}
// ── Shared Managers ──────────────────────────────────
SSApiManager.EnsureInstance();
SetupAudioManager();
SetupParticleManager();
var session = SSGameSession.EnsureInstance();
session.buildType = buildType;
session.gradeId = gradeId;
session.questionCount = questionCount;
session.classCode = classCode;
yield return null;
// ── Camera ───────────────────────────────────────────
SetupCamera();
yield return null;
// ── Environment ──────────────────────────────────────
if (environmentPrefab != null)
Instantiate(environmentPrefab, Vector3.zero, Quaternion.identity);
yield return null;
// ── Lighting ─────────────────────────────────────────
SetupLighting();
yield return null;
// ── Bot ──────────────────────────────────────────────
if (botPrefab != null)
{
var botObj = Instantiate(botPrefab, botSpawnPosition, Quaternion.identity);
botObj.name = "Bot";
_bot = botObj.GetComponent<CsBotController>();
if (_bot == null)
{
Debug.LogError("[CS] Bot prefab is missing CsBotController!");
yield break;
}
// If your prefab's Build() still needs calling (e.g. for animations):
// _bot.Build(); ← uncomment if the prefab needs runtime init
}
else
{
// Fallback: procedural bot
var botObj = new GameObject("Bot");
botObj.transform.position = botSpawnPosition;
_bot = botObj.AddComponent<CsBotController>();
_bot.Build();
}
yield return null;
// ── Word Container ───────────────────────────────────
var wordContainer = new GameObject("WordContainer");
wordContainer.transform.position = Vector3.zero;
yield return null;
// ── UI ───────────────────────────────────────────────
if (canvasPrefab != null)
{
var canvasObj = Instantiate(canvasPrefab);
canvasObj.name = "CsUI";
_uiManager = canvasObj.GetComponentInChildren<CsUIManager>();
if (_uiManager == null)
{
Debug.LogError("[CS] Canvas prefab is missing CsUIManager!");
yield break;
}
// Don't call BuildUI — prefab is already set up
}
else
{
// Fallback: procedural UI
var uiObj = new GameObject("CsUI");
_uiManager = uiObj.AddComponent<CsUIManager>();
_uiManager.BuildUI();
}
if (_uiManager.onRestartClicked == null)
_uiManager.onRestartClicked = new UnityEvent();
yield return null;
// ── Game Manager ─────────────────────────────────────
var gmObj = new GameObject("CsGameManager");
_gm = gmObj.AddComponent<CsGameManager>();
_gm.bot = _bot;
_gm.uiManager = _uiManager;
_gm.wordContainer = wordContainer.transform;
_uiManager.onRestartClicked.AddListener(OnRestartClicked);
yield return null;
Debug.Log("═══ CS Game built! Starting... ═══");
yield return new WaitForSeconds(0.5f);
if (useOfflineTestData)
_gm.StartWithQuestions(GetTestQuestions());
else
_gm.StartGame();
}
// ════════════════════════════════════════════════════════════
// SETUP HELPERS
// ════════════════════════════════════════════════════════════
private void SetupCamera()
{
var cam = cameraOverride != null ? cameraOverride : Camera.main;
if (cam == null) return;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = cameraBgColor;
cam.transform.position = cameraPosition;
cam.transform.rotation = Quaternion.Euler(cameraRotation);
cam.fieldOfView = cameraFOV;
cam.nearClipPlane = 0.1f;
}
private void SetupLighting()
{
if (directionalLightPrefab != null)
Instantiate(directionalLightPrefab);
if (extraLightPrefabs != null)
{
foreach (var lp in extraLightPrefabs)
if (lp != null) Instantiate(lp);
}
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
RenderSettings.ambientLight = ambientColor;
}
private void SetupAudioManager()
{
var audio = SSAudioManager.EnsureInstance();
if (sfxCorrect != null) audio.sfxCorrect = sfxCorrect;
if (sfxWrong != null) audio.sfxWrong = sfxWrong;
if (sfxClick != null) audio.sfxClick = sfxClick;
if (sfxVictory != null) audio.sfxVictory = sfxVictory;
if (sfxDefeat != null) audio.sfxDefeat = sfxDefeat;
if (sfxWhoosh != null) audio.sfxWhoosh = sfxWhoosh;
if (sfxPop != null) audio.sfxPop = sfxPop;
if (sfxSlam != null) audio.sfxSlam = sfxSlam;
if (sfxCheer != null) audio.sfxCheer = sfxCheer;
}
private void SetupParticleManager()
{
var particles = SSParticleManager.EnsureInstance();
if (correctBurstParticle != null) particles.correctBurstPrefab = correctBurstParticle;
if (wrongBurstParticle != null) particles.wrongBurstPrefab = wrongBurstParticle;
if (confettiParticle != null) particles.confettiPrefab = confettiParticle;
if (sparksParticle != null) particles.sparksPrefab = sparksParticle;
if (starBurstParticle != null) particles.starBurstPrefab = starBurstParticle;
}
private void OnRestartClicked()
{
if (_gm != null) _gm.ResetGame();
if (_gm != null) _gm.StartGame();
}
// ════════════════════════════════════════════════════════════
// OFFLINE TEST DATA
// ════════════════════════════════════════════════════════════
private CsQuestion[] GetTestQuestions()
{
return new CsQuestion[]
{
new()
{
id = "1", source = "علوم",
wrong_word = "القمر", correct_answer = "الشمس",
words = new CsWord[]
{
new() { word_text = "القمر", position = 0, is_wrong = true },
new() { word_text = "مصدر", position = 1, is_wrong = false },
new() { word_text = "الضوء", position = 2, is_wrong = false },
new() { word_text = "والحرارة", position = 3, is_wrong = false },
new() { word_text = "للأرض", position = 4, is_wrong = false },
},
options = new CsOption[]
{
new() { option_text = "الشمس", is_correct = true },
new() { option_text = "النجوم", is_correct = false },
new() { option_text = "الكواكب", is_correct = false },
}
},
new()
{
id = "2", source = "جغرافيا",
wrong_word = "خمس", correct_answer = "سبع",
words = new CsWord[]
{
new() { word_text = "يتكون", position = 0, is_wrong = false },
new() { word_text = "العالم", position = 1, is_wrong = false },
new() { word_text = "من", position = 2, is_wrong = false },
new() { word_text = "خمس", position = 3, is_wrong = true },
new() { word_text = "قارات", position = 4, is_wrong = false },
},
options = new CsOption[]
{
new() { option_text = "ست", is_correct = false },
new() { option_text = "سبع", is_correct = true },
new() { option_text = "ثمان", is_correct = false },
}
},
};
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: f01ccea8ba624884b1d770a47d7e8a11
timeCreated: 1771777444
\ No newline at end of file
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using DG.Tweening;
using TMPro;
namespace com.al_arcade.mcq
{
using shared;
[AddComponentMenu("Science Street/MCQ Prefab Builder")]
public class McqPrefabBuilder : MonoBehaviour
{
// ════════════════════════════════════════════════════════════
// SCENE
// ════════════════════════════════════════════════════════════
[Header("Scene Environment")]
[Tooltip("Your full road/environment prefab. Spawned at origin.")]
[SerializeField] private GameObject environmentPrefab;
[Header("Camera")]
[SerializeField] private Vector3 cameraOffset = new Vector3(0, 5f, -8f);
[SerializeField] private Vector3 cameraLookOffset = new Vector3(0, 1.5f, 12f);
[SerializeField] private float cameraSmoothSpeed = 6f;
[SerializeField] private Color cameraBgColor = new Color32(180, 200, 240, 255);
// ════════════════════════════════════════════════════════════
// LIGHTING
// ════════════════════════════════════════════════════════════
[Header("Lighting")]
[SerializeField] private GameObject directionalLightPrefab;
[SerializeField] private GameObject[] extraLightPrefabs;
[SerializeField] private Color ambientColor = new Color32(80, 85, 110, 255);
// ════════════════════════════════════════════════════════════
// PLAYER
// ════════════════════════════════════════════════════════════
[Header("Player")]
[Tooltip("Your player prefab. MUST have McqPlayerRunner + Rigidbody + Collider.\n" +
"Tag it 'Player'. If null, a procedural player is created.")]
[SerializeField] private GameObject playerPrefab;
[SerializeField] private Vector3 playerSpawnPosition = Vector3.zero;
// ════════════════════════════════════════════════════════════
// GATE
// ════════════════════════════════════════════════════════════
[Header("Answer Gate")]
[Tooltip("Your gate prefab. MUST have McqGateController.\n" +
"If null, the procedural gate is used.")]
[SerializeField] private GameObject gatePrefab;
// ════════════════════════════════════════════════════════════
// QUESTION DISPLAY
// ════════════════════════════════════════════════════════════
[Header("Question Display")]
[Tooltip("Your question display prefab. MUST have McqQuestionDisplay.\n" +
"If null, a procedural one is created.")]
[SerializeField] private GameObject questionDisplayPrefab;
[SerializeField] private Vector3 questionDisplayOffset = new Vector3(0, 8, 10);
// ════════════════════════════════════════════════════════════
// UI
// ════════════════════════════════════════════════════════════
[Header("UI Canvas")]
[Tooltip("Your Canvas prefab. MUST have McqUIManager with all references wired.\n" +
"If null, procedural UI is created.")]
[SerializeField] private GameObject canvasPrefab;
// ════════════════════════════════════════════════════════════
// AUDIO
// ════════════════════════════════════════════════════════════
[Header("Audio — SFX Clips")]
[SerializeField] private AudioClip sfxCorrect;
[SerializeField] private AudioClip sfxWrong;
[SerializeField] private AudioClip sfxClick;
[SerializeField] private AudioClip sfxVictory;
[SerializeField] private AudioClip sfxDefeat;
[SerializeField] private AudioClip sfxWhoosh;
[SerializeField] private AudioClip sfxPop;
[SerializeField] private AudioClip sfxCheer;
[SerializeField] private AudioClip sfxCountdown;
// ════════════════════════════════════════════════════════════
// PARTICLES
// ════════════════════════════════════════════════════════════
[Header("Particles")]
[SerializeField] private ParticleSystem correctBurstParticle;
[SerializeField] private ParticleSystem wrongBurstParticle;
[SerializeField] private ParticleSystem confettiParticle;
[SerializeField] private ParticleSystem sparksParticle;
[SerializeField] private ParticleSystem starBurstParticle;
// ════════════════════════════════════════════════════════════
// FONT
// ════════════════════════════════════════════════════════════
[Header("Arabic Font")]
[SerializeField] private TMP_FontAsset arabicFont;
// ════════════════════════════════════════════════════════════
// GAME SETTINGS
// ════════════════════════════════════════════════════════════
[Header("Game Settings")]
[SerializeField] private string buildType = "scistreet";
[SerializeField] private int gradeId = 0;
[SerializeField] private int questionCount = 10;
[SerializeField] private string classCode = "";
[SerializeField] private float runSpeed = 12f;
[SerializeField] private int lives = 3;
[Header("Debug")]
[SerializeField] private bool useOfflineTestData = false;
// ════════════════════════════════════════════════════════════
// RUNTIME
// ════════════════════════════════════════════════════════════
private McqGameManager _gm;
private McqPlayerRunner _player;
private McqQuestionDisplay _questionDisplay;
private McqUIManager _uiManager;
private void Start()
{
DOTween.Init();
if (arabicFont != null) SSFontManager.Font = arabicFont;
StartCoroutine(BuildEverything());
}
private IEnumerator BuildEverything()
{
Debug.Log("═══ MCQ Prefab Builder — Starting ═══");
// ── EventSystem ──────────────────────────────────────
if (FindObjectOfType<EventSystem>() == null)
{
var es = new GameObject("EventSystem");
es.AddComponent<EventSystem>();
es.AddComponent<StandaloneInputModule>();
}
// ── Shared Managers ──────────────────────────────────
SSApiManager.EnsureInstance();
SetupAudioManager();
SetupParticleManager();
var session = SSGameSession.EnsureInstance();
session.buildType = buildType;
session.gradeId = gradeId;
session.questionCount = questionCount;
session.classCode = classCode;
yield return null;
// ── Environment ──────────────────────────────────────
if (environmentPrefab != null)
Instantiate(environmentPrefab, Vector3.zero, Quaternion.identity);
yield return null;
// ── Player ───────────────────────────────────────────
if (playerPrefab != null)
{
var playerObj = Instantiate(playerPrefab, playerSpawnPosition, Quaternion.identity);
playerObj.name = "Player";
if (!playerObj.CompareTag("Player"))
playerObj.tag = "Player";
_player = playerObj.GetComponent<McqPlayerRunner>();
if (_player == null)
{
Debug.LogError("[MCQ] Player prefab missing McqPlayerRunner!");
yield break;
}
// Ensure Rigidbody
var rb = playerObj.GetComponent<Rigidbody>();
if (rb == null) rb = playerObj.AddComponent<Rigidbody>();
rb.isKinematic = true;
rb.useGravity = false;
}
else
{
var obj = new GameObject("Player");
obj.tag = "Player";
obj.transform.position = playerSpawnPosition;
_player = obj.AddComponent<McqPlayerRunner>();
_player.BuildDefaultVisuals();
var rb = obj.GetComponent<Rigidbody>();
if (rb == null) rb = obj.AddComponent<Rigidbody>();
rb.isKinematic = true;
rb.useGravity = false;
}
yield return null;
// ── Question Display ─────────────────────────────────
if (questionDisplayPrefab != null)
{
var qdObj = Instantiate(questionDisplayPrefab,
_player.transform.position + questionDisplayOffset,
Quaternion.identity);
qdObj.name = "QuestionDisplay";
_questionDisplay = qdObj.GetComponent<McqQuestionDisplay>();
if (_questionDisplay == null)
{
Debug.LogError("[MCQ] QuestionDisplay prefab missing McqQuestionDisplay!");
yield break;
}
}
else
{
var obj = new GameObject("QuestionDisplay");
obj.transform.position = _player.transform.position + questionDisplayOffset;
_questionDisplay = obj.AddComponent<McqQuestionDisplay>();
_questionDisplay.Build(_player.transform);
}
yield return null;
// ── UI ───────────────────────────────────────────────
if (canvasPrefab != null)
{
var canvasObj = Instantiate(canvasPrefab);
canvasObj.name = "McqUI";
_uiManager = canvasObj.GetComponentInChildren<McqUIManager>();
if (_uiManager == null)
{
Debug.LogError("[MCQ] Canvas prefab missing McqUIManager!");
yield break;
}
}
else
{
var obj = new GameObject("McqUI");
_uiManager = obj.AddComponent<McqUIManager>();
_uiManager.BuildUI();
}
if (_uiManager.onRestartClicked == null)
_uiManager.onRestartClicked = new UnityEvent();
yield return null;
// ── Game Manager ─────────────────────────────────────
var gmObj = new GameObject("McqGameManager");
_gm = gmObj.AddComponent<McqGameManager>();
_gm.player = _player;
_gm.questionDisplay = _questionDisplay;
_gm.uiManager = _uiManager;
_gm.gateParent = new GameObject("Gates").transform;
_uiManager.onRestartClicked.AddListener(OnRestartClicked);
yield return null;
// ── Camera ───────────────────────────────────────────
SetupCamera();
yield return null;
// ── Lighting ─────────────────────────────────────────
SetupLighting();
yield return null;
Debug.Log("═══ MCQ Ready — A/D or ←/→ to steer ═══");
yield return new WaitForSeconds(0.3f);
if (useOfflineTestData)
_gm.StartWithQuestions(GetTestQuestions());
else
_gm.StartGame();
}
// ════════════════════════════════════════════════════════════
// SETUP
// ════════════════════════════════════════════════════════════
private void SetupCamera()
{
var cam = Camera.main;
if (cam == null) return;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = cameraBgColor;
var follower = cam.GetComponent<McqCameraFollow>();
if (follower == null)
follower = cam.gameObject.AddComponent<McqCameraFollow>();
follower.target = _player != null ? _player.transform : null;
follower.offset = cameraOffset;
follower.lookOffset = cameraLookOffset;
follower.smoothSpeed = cameraSmoothSpeed;
}
private void SetupLighting()
{
if (directionalLightPrefab != null)
Instantiate(directionalLightPrefab);
if (extraLightPrefabs != null)
foreach (var lp in extraLightPrefabs)
if (lp != null) Instantiate(lp);
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
RenderSettings.ambientLight = ambientColor;
}
private void SetupAudioManager()
{
var a = SSAudioManager.EnsureInstance();
if (sfxCorrect != null) a.sfxCorrect = sfxCorrect;
if (sfxWrong != null) a.sfxWrong = sfxWrong;
if (sfxClick != null) a.sfxClick = sfxClick;
if (sfxVictory != null) a.sfxVictory = sfxVictory;
if (sfxDefeat != null) a.sfxDefeat = sfxDefeat;
if (sfxWhoosh != null) a.sfxWhoosh = sfxWhoosh;
if (sfxPop != null) a.sfxPop = sfxPop;
if (sfxCheer != null) a.sfxCheer = sfxCheer;
if (sfxCountdown != null) a.sfxCountdown = sfxCountdown;
}
private void SetupParticleManager()
{
var p = SSParticleManager.EnsureInstance();
if (correctBurstParticle != null) p.correctBurstPrefab = correctBurstParticle;
if (wrongBurstParticle != null) p.wrongBurstPrefab = wrongBurstParticle;
if (confettiParticle != null) p.confettiPrefab = confettiParticle;
if (sparksParticle != null) p.sparksPrefab = sparksParticle;
if (starBurstParticle != null) p.starBurstPrefab = starBurstParticle;
}
private void OnRestartClicked()
{
if (_gm != null) _gm.ResetGame();
if (_player != null) _player.ResetToStart();
SetupCamera();
if (_gm != null) _gm.StartGame();
}
private McqQuestion[] GetTestQuestions()
{
return new McqQuestion[]
{
new() { id="1", question_text="ما هي عاصمة مصر؟",
answer1="القاهرة", answer2="الإسكندرية",
answer3="أسوان", answer4="المنصورة", source="جغرافيا" },
new() { id="2", question_text="كم عدد كواكب المجموعة الشمسية؟",
answer1="8", answer2="9",
answer3="7", answer4="10", source="علوم" },
new() { id="3", question_text="ما هو أكبر محيط في العالم؟",
answer1="المحيط الهادي", answer2="المحيط الأطلسي",
answer3="المحيط الهندي", answer4="المحيط المتجمد", source="جغرافيا" },
};
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 9f0189b5f38d46349ea6346967d8f9d9
timeCreated: 1771777421
\ No newline at end of file
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using DG.Tweening;
using TMPro;
namespace com.al_arcade.tf
{
using shared;
[AddComponentMenu("Science Street/TF Prefab Builder")]
public class TfPrefabBuilder : MonoBehaviour
{
// ════════════════════════════════════════════════════════════
// SCENE
// ════════════════════════════════════════════════════════════
[Header("Scene Environment")]
[Tooltip("Your full factory environment prefab.")]
[SerializeField] private GameObject environmentPrefab;
[Header("Camera")]
[SerializeField] private Vector3 cameraPosition = new Vector3(-11f, 3.5f, 12f);
[SerializeField] private Vector3 cameraLookAt = new Vector3(0f, 1.5f, 12f);
[SerializeField] private float cameraFOV = 55f;
[SerializeField] private Color cameraBgColor = new Color32(70, 80, 110, 255);
// ════════════════════════════════════════════════════════════
// LIGHTING
// ════════════════════════════════════════════════════════════
[Header("Lighting")]
[SerializeField] private GameObject directionalLightPrefab;
[SerializeField] private GameObject[] extraLightPrefabs;
[SerializeField] private Color ambientColor = new Color32(75, 78, 95, 255);
// ════════════════════════════════════════════════════════════
// PRODUCTION LINE
// ════════════════════════════════════════════════════════════
[Header("Production Line")]
[Tooltip("Your production line prefab. MUST have TfProductionLine.\n" +
"If null, a procedural one is created.")]
[SerializeField] private GameObject productionLinePrefab;
[SerializeField] private Vector3 productionLinePosition = new Vector3(0, 0, 2);
// ════════════════════════════════════════════════════════════
// QUESTION SCREEN
// ════════════════════════════════════════════════════════════
[Header("Question Screen")]
[Tooltip("Your question screen prefab. MUST have TfQuestionScreen.\n" +
"If null, a procedural one is created.")]
[SerializeField] private GameObject questionScreenPrefab;
[SerializeField] private Vector3 questionScreenPosition = new Vector3(0, 5f, 12f);
// ════════════════════════════════════════════════════════════
// HANDS
// ════════════════════════════════════════════════════════════
[Header("Hands / Buttons")]
[Tooltip("Your hands prefab. MUST have TfHandController.\n" +
"If null, procedural hands are created.")]
[SerializeField] private GameObject handsPrefab;
// ════════════════════════════════════════════════════════════
// UI
// ════════════════════════════════════════════════════════════
[Header("UI Canvas")]
[Tooltip("Your Canvas prefab. MUST have TfUIManager with all references wired.\n" +
"If null, procedural UI is created.")]
[SerializeField] private GameObject canvasPrefab;
// ════════════════════════════════════════════════════════════
// AUDIO
// ════════════════════════════════════════════════════════════
[Header("Audio — SFX Clips")]
[SerializeField] private AudioClip sfxCorrect;
[SerializeField] private AudioClip sfxWrong;
[SerializeField] private AudioClip sfxClick;
[SerializeField] private AudioClip sfxVictory;
[SerializeField] private AudioClip sfxDefeat;
[SerializeField] private AudioClip sfxWhoosh;
[SerializeField] private AudioClip sfxPop;
[SerializeField] private AudioClip sfxSlam;
// ════════════════════════════════════════════════════════════
// PARTICLES
// ════════════════════════════════════════════════════════════
[Header("Particles")]
[SerializeField] private ParticleSystem correctBurstParticle;
[SerializeField] private ParticleSystem wrongBurstParticle;
[SerializeField] private ParticleSystem confettiParticle;
[SerializeField] private ParticleSystem sparksParticle;
[SerializeField] private ParticleSystem starBurstParticle;
// ════════════════════════════════════════════════════════════
// FONT
// ════════════════════════════════════════════════════════════
[Header("Arabic Font")]
[SerializeField] private TMP_FontAsset arabicFont;
// ════════════════════════════════════════════════════════════
// GAME SETTINGS
// ════════════════════════════════════════════════════════════
[Header("Game Settings")]
[SerializeField] private string buildType = "scistreet";
[SerializeField] private int gradeId = 0;
[SerializeField] private int questionCount = 15;
[SerializeField] private string classCode = "";
[SerializeField] private int stepsToWin = 5;
[SerializeField] private float stepDistance = 3f;
[Header("Debug")]
[SerializeField] private bool useOfflineTestData = false;
// ════════════════════════════════════════════════════════════
// RUNTIME
// ════════════════════════════════════════════════════════════
private TfGameManager _gm;
private TfHandController _handController;
private TfProductionLine _productionLine;
private TfQuestionScreen _questionScreen;
private TfUIManager _uiManager;
private void Start()
{
DOTween.Init();
if (arabicFont != null) SSFontManager.Font = arabicFont;
StartCoroutine(BuildEverything());
}
private IEnumerator BuildEverything()
{
Debug.Log("═══ TF Prefab Builder — Starting ═══");
if (FindObjectOfType<EventSystem>() == null)
{
var es = new GameObject("EventSystem");
es.AddComponent<EventSystem>();
es.AddComponent<StandaloneInputModule>();
}
SSApiManager.EnsureInstance();
SetupAudioManager();
SetupParticleManager();
var session = SSGameSession.EnsureInstance();
session.buildType = buildType;
session.gradeId = gradeId;
session.questionCount = questionCount;
session.classCode = classCode;
yield return null;
// ── Camera ───────────────────────────────────────────
SetupCamera();
yield return null;
// ── Environment ──────────────────────────────────────
if (environmentPrefab != null)
Instantiate(environmentPrefab, Vector3.zero, Quaternion.identity);
yield return null;
// ── Lighting ─────────────────────────────────────────
SetupLighting();
yield return null;
// ── Production Line ──────────────────────────────────
if (productionLinePrefab != null)
{
var lineObj = Instantiate(productionLinePrefab,
productionLinePosition, Quaternion.identity);
lineObj.name = "ProductionLine";
_productionLine = lineObj.GetComponent<TfProductionLine>();
if (_productionLine == null)
{
Debug.LogError("[TF] ProductionLine prefab missing TfProductionLine!");
yield break;
}
}
else
{
var lineObj = new GameObject("ProductionLine");
lineObj.transform.position = productionLinePosition;
_productionLine = lineObj.AddComponent<TfProductionLine>();
_productionLine.Build(stepsToWin, stepDistance, cameraPosition);
}
yield return null;
// ── Question Screen ──────────────────────────────────
if (questionScreenPrefab != null)
{
var screenObj = Instantiate(questionScreenPrefab,
questionScreenPosition, Quaternion.identity);
screenObj.name = "QuestionScreen";
_questionScreen = screenObj.GetComponent<TfQuestionScreen>();
if (_questionScreen == null)
{
Debug.LogError("[TF] QuestionScreen prefab missing TfQuestionScreen!");
yield break;
}
}
else
{
var screenObj = new GameObject("QuestionScreen");
_questionScreen = screenObj.AddComponent<TfQuestionScreen>();
_questionScreen.Build(questionScreenPosition, cameraPosition);
}
yield return null;
// ── Hands ────────────────────────────────────────────
if (handsPrefab != null)
{
var handsObj = Instantiate(handsPrefab);
handsObj.name = "Hands";
_handController = handsObj.GetComponent<TfHandController>();
if (_handController == null)
{
Debug.LogError("[TF] Hands prefab missing TfHandController!");
yield break;
}
}
else
{
var handsObj = new GameObject("Hands");
_handController = handsObj.AddComponent<TfHandController>();
_handController.Build(Camera.main);
}
yield return null;
// ── UI ───────────────────────────────────────────────
if (canvasPrefab != null)
{
var canvasObj = Instantiate(canvasPrefab);
canvasObj.name = "TfUI";
_uiManager = canvasObj.GetComponentInChildren<TfUIManager>();
if (_uiManager == null)
{
Debug.LogError("[TF] Canvas prefab missing TfUIManager!");
yield break;
}
}
else
{
var uiObj = new GameObject("TfUI");
_uiManager = uiObj.AddComponent<TfUIManager>();
_uiManager.BuildUI();
}
if (_uiManager.onRestartClicked == null)
_uiManager.onRestartClicked = new UnityEvent();
yield return null;
// ── Game Manager ─────────────────────────────────────
var gmObj = new GameObject("TfGameManager");
_gm = gmObj.AddComponent<TfGameManager>();
_gm.handController = _handController;
_gm.productionLine = _productionLine;
_gm.questionScreen = _questionScreen;
_gm.uiManager = _uiManager;
_uiManager.onRestartClicked.AddListener(OnRestartClicked);
yield return null;
Debug.Log("═══ TF Ready! A/← = True D/→ = False ═══");
yield return new WaitForSeconds(0.5f);
if (useOfflineTestData)
_gm.StartWithQuestions(GetTestQuestions());
else
_gm.StartGame();
}
private void SetupCamera()
{
var cam = Camera.main;
if (cam == null) return;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = cameraBgColor;
cam.transform.position = cameraPosition;
cam.transform.LookAt(cameraLookAt);
cam.fieldOfView = cameraFOV;
cam.nearClipPlane = 0.1f;
}
private void SetupLighting()
{
if (directionalLightPrefab != null)
Instantiate(directionalLightPrefab);
if (extraLightPrefabs != null)
foreach (var lp in extraLightPrefabs)
if (lp != null) Instantiate(lp);
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
RenderSettings.ambientLight = ambientColor;
}
private void SetupAudioManager()
{
var a = SSAudioManager.EnsureInstance();
if (sfxCorrect != null) a.sfxCorrect = sfxCorrect;
if (sfxWrong != null) a.sfxWrong = sfxWrong;
if (sfxClick != null) a.sfxClick = sfxClick;
if (sfxVictory != null) a.sfxVictory = sfxVictory;
if (sfxDefeat != null) a.sfxDefeat = sfxDefeat;
if (sfxWhoosh != null) a.sfxWhoosh = sfxWhoosh;
if (sfxPop != null) a.sfxPop = sfxPop;
if (sfxSlam != null) a.sfxSlam = sfxSlam;
}
private void SetupParticleManager()
{
var p = SSParticleManager.EnsureInstance();
if (correctBurstParticle != null) p.correctBurstPrefab = correctBurstParticle;
if (wrongBurstParticle != null) p.wrongBurstPrefab = wrongBurstParticle;
if (confettiParticle != null) p.confettiPrefab = confettiParticle;
if (sparksParticle != null) p.sparksPrefab = sparksParticle;
if (starBurstParticle != null) p.starBurstPrefab = starBurstParticle;
}
private void OnRestartClicked()
{
if (_gm != null) _gm.ResetGame();
SetupCamera();
if (_gm != null) _gm.StartGame();
}
private TfQuestion[] GetTestQuestions()
{
return new TfQuestion[]
{
new() { id="1", question_text="الشمس تدور حول الأرض",
is_true=false, source="علوم" },
new() { id="2", question_text="الماء يتكون من الهيدروجين والأكسجين",
is_true=true, source="كيمياء" },
new() { id="3", question_text="القمر ينير بذاته",
is_true=false, source="فلك" },
new() { id="4", question_text="النباتات تحتاج ضوء الشمس لعملية البناء الضوئي",
is_true=true, source="أحياء" },
new() { id="5", question_text="الحديد يتمدد بالحرارة",
is_true=true, source="فيزياء" },
};
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: d528eb68fea941108f16e8f7bc09eac1
timeCreated: 1771777396
\ No newline at end of file
......@@ -15,9 +15,9 @@ MonoBehaviour:
m_PixelRect:
serializedVersion: 2
x: 0
y: 0
width: 2560
height: 1440
y: 61
width: 1512
height: 921
m_ShowMode: 4
m_Title: Inspector
m_RootView: {fileID: 2}
......@@ -44,8 +44,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 2560
height: 1440
width: 1512
height: 921
m_MinSize: {x: 875, y: 300}
m_MaxSize: {x: 10000, y: 10000}
m_UseTopView: 1
......@@ -69,7 +69,7 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 2560
width: 1512
height: 36
m_MinSize: {x: 50, y: 50}
m_MaxSize: {x: 4000, y: 4000}
......@@ -90,8 +90,8 @@ MonoBehaviour:
m_Position:
serializedVersion: 2
x: 0
y: 1420
width: 2560
y: 901
width: 1512
height: 20
m_MinSize: {x: 0, y: 0}
m_MaxSize: {x: 0, y: 0}
......@@ -114,8 +114,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 36
width: 2560
height: 1384
width: 1512
height: 865
m_MinSize: {x: 300, y: 112}
m_MaxSize: {x: 24288, y: 16192}
vertical: 0
......@@ -140,8 +140,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 1955
height: 1384
width: 1154.5
height: 865
m_MinSize: {x: 200, y: 112}
m_MaxSize: {x: 16192, y: 16192}
vertical: 1
......@@ -166,8 +166,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 1955
height: 961
width: 1154.5
height: 600.5
m_MinSize: {x: 200, y: 56}
m_MaxSize: {x: 16192, y: 8096}
vertical: 0
......@@ -190,10 +190,10 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 484
height: 961
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 4000, y: 4000}
width: 286
height: 600.5
m_MinSize: {x: 201, y: 226}
m_MaxSize: {x: 4001, y: 4026}
m_ActualView: {fileID: 14}
m_Panes:
- {fileID: 14}
......@@ -214,10 +214,10 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 484
x: 286
y: 0
width: 1471
height: 961
width: 868.5
height: 600.5
m_MinSize: {x: 202, y: 226}
m_MaxSize: {x: 4002, y: 4026}
m_ActualView: {fileID: 15}
......@@ -242,9 +242,9 @@ MonoBehaviour:
m_Position:
serializedVersion: 2
x: 0
y: 961
width: 1955
height: 423
y: 600.5
width: 1154.5
height: 264.5
m_MinSize: {x: 231, y: 276}
m_MaxSize: {x: 10001, y: 10026}
m_ActualView: {fileID: 16}
......@@ -268,12 +268,12 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 1955
x: 1154.5
y: 0
width: 605
height: 1384
m_MinSize: {x: 275, y: 50}
m_MaxSize: {x: 4000, y: 4000}
width: 357.5
height: 865
m_MinSize: {x: 276, y: 76}
m_MaxSize: {x: 4001, y: 4026}
m_ActualView: {fileID: 18}
m_Panes:
- {fileID: 18}
......@@ -302,7 +302,7 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 2560
width: 1512
height: 36
m_SerializedDataModeController:
m_DataMode: 0
......@@ -561,7 +561,7 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Game
m_Image: {fileID: -6423792434712278376, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: 4621777727084837110, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Game\u200B"
m_Pos:
......@@ -604,10 +604,10 @@ MonoBehaviour:
m_VRangeLocked: 0
hZoomLockedByDefault: 0
vZoomLockedByDefault: 0
m_HBaseRangeMin: -734.5
m_HBaseRangeMax: 734.5
m_VBaseRangeMin: -457
m_VBaseRangeMax: 457
m_HBaseRangeMin: -367.25
m_HBaseRangeMax: 367.25
m_VBaseRangeMin: -228.5
m_VBaseRangeMax: 228.5
m_HAllowExceedBaseRangeMin: 1
m_HAllowExceedBaseRangeMax: 1
m_VAllowExceedBaseRangeMin: 1
......@@ -627,7 +627,7 @@ MonoBehaviour:
y: 21
width: 1469
height: 914
m_Scale: {x: 1, y: 1}
m_Scale: {x: 2, y: 2}
m_Translation: {x: 734.5, y: 457}
m_MarginLeft: 0
m_MarginRight: 0
......@@ -635,13 +635,13 @@ MonoBehaviour:
m_MarginBottom: 0
m_LastShownAreaInsideMargins:
serializedVersion: 2
x: -734.5
y: -457
width: 1469
height: 914
x: -367.25
y: -228.5
width: 734.5
height: 457
m_MinimalGUI: 1
m_defaultScale: 1
m_LastWindowPixelSize: {x: 1469, y: 935}
m_defaultScale: 2
m_LastWindowPixelSize: {x: 2938, y: 1870}
m_ClearInEditMode: 1
m_NoCameraWarning: 1
m_LowResolutionForAspectRatios: 01000000000000000000
......@@ -664,15 +664,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Hierarchy
m_Image: {fileID: 7966133145522015247, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -3734745235275155857, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Hierarchy\u200B"
m_Pos:
serializedVersion: 2
x: 0
y: 36
width: 483
height: 935
y: 24
width: 285
height: 574.5
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -689,8 +689,7 @@ MonoBehaviour:
m_SceneHierarchy:
m_TreeViewState:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
- m_Data: 49284
m_SelectedIDs: []
m_LastClickedID:
m_Data: 0
m_ExpandedIDs:
......@@ -736,15 +735,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Scene
m_Image: {fileID: 2593428753322112591, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: 8634526014445323508, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Scene\u200B"
m_Pos:
serializedVersion: 2
x: 484
y: 36
width: 1469
height: 935
x: 287
y: 24
width: 866.5
height: 574.5
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1351,7 +1350,7 @@ MonoBehaviour:
m_Rotation:
m_Target: {x: -0.18071716, y: 0.03156269, z: -0.005801803, w: -0.98301476}
speed: 2
m_Value: {x: -0.18071657, y: 0.03156259, z: -0.0058017843, w: -0.9830116}
m_Value: {x: -0.18071716, y: 0.03156269, z: -0.005801803, w: -0.98301476}
m_Size:
m_Target: 19.357506
speed: 2
......@@ -1405,15 +1404,15 @@ MonoBehaviour:
m_MaxSize: {x: 10000, y: 10000}
m_TitleContent:
m_Text: Project
m_Image: {fileID: -5467254957812901981, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -5179483145760003458, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Project\u200B"
m_Pos:
serializedVersion: 2
x: 0
y: 997
width: 1954
height: 397
y: 624.5
width: 1153.5
height: 238.5
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1462,13 +1461,9 @@ MonoBehaviour:
m_Data: 49284
m_ExpandedIDs:
- m_Data: 0
- m_Data: 46230
- m_Data: 46232
- m_Data: 46234
- m_Data: 46404
- m_Data: 47754
- m_Data: 47758
- m_Data: 1000000000
- m_Data: 45886
- m_Data: 45888
- m_Data: 45890
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -1501,10 +1496,9 @@ MonoBehaviour:
m_Data: 0
m_ExpandedIDs:
- m_Data: 0
- m_Data: 46230
- m_Data: 46232
- m_Data: 46234
- m_Data: 1000000000
- m_Data: 45886
- m_Data: 45888
- m_Data: 45890
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -1581,7 +1575,7 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Console
m_Image: {fileID: -4327648978806127646, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -4950941429401207979, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Console\u200B"
m_Pos:
......@@ -1619,15 +1613,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Inspector
m_Image: {fileID: -2667387946076563598, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -440750813802333266, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Inspector\u200B"
m_Pos:
serializedVersion: 2
x: 1955
y: 36
width: 604
height: 1358
x: 1155.5
y: 24
width: 356.5
height: 839
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment