| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566 |
- using UnityEngine;
- using System.Collections.Generic;
- public class NewRoomBuilder : MonoBehaviour
- {
- [Header("Prefabs")]
- public GameObject wallPrefab;
- public GameObject wallPointPrefab;
- public GameObject doorOpeningPrefab;
- [Header("Settings")]
- public float wallHeight = 3f;
- public float wallThickness = 0.2f;
- public float doorWidth = 1.5f;
- public float doorHeight = 2.5f;
- public float snapDistance = 1f; // Distance for snapping to existing points
- private Camera playerCamera;
- private BuildingUIController.BuildingMode currentMode = BuildingUIController.BuildingMode.Normal;
- // Wall creation state
- private bool isCreatingWall = false;
- private Vector3 wallStartPoint;
- private GameObject previewWall;
- private LineRenderer previewLine;
- // Available angles (in degrees)
- private readonly float[] snapAngles = { 0f, 45f, 90f, 135f, 180f, 225f, 270f, 315f };
- // Wall storage
- private List<GameObject> walls = new List<GameObject>();
- // Door preview
- private GameObject doorPreview;
- private GameObject hoveredWall;
- // Snap indicators
- private GameObject snapIndicator;
- private GameObject currentSnapPoint;
- private void Start()
- {
- // Try multiple ways to find the camera
- playerCamera = Camera.main;
- if (playerCamera == null)
- {
- playerCamera = FindFirstObjectByType<Camera>();
- Debug.LogWarning($"Camera.main was null, found camera: {playerCamera?.name ?? "NONE"}");
- }
- if (playerCamera == null)
- {
- Debug.LogError("No camera found! Wall detection will not work.");
- }
- else
- {
- Debug.Log($"Using camera: {playerCamera.name} at {playerCamera.transform.position}");
- }
- CreatePreviewLine();
- CreateDoorPreview();
- CreateSnapIndicator();
- // Ensure we have prefabs
- EnsurePrefabsExist();
- // Fix any existing walls that might not be tagged properly
- FixExistingWallTags();
- }
- private void FixExistingWallTags()
- {
- // First, look for walls that are already properly tagged (from InitialRoomSetup)
- GameObject[] existingWalls = GameObject.FindGameObjectsWithTag("Wall");
- Debug.Log($"Found {existingWalls.Length} objects already tagged as 'Wall'");
- foreach (GameObject wall in existingWalls)
- {
- if (!walls.Contains(wall))
- {
- walls.Add(wall);
- Debug.Log($"Added existing tagged wall to tracking: {wall.name} - Scale: {wall.transform.localScale}");
- }
- }
- // If we found properly tagged walls, we're done
- if (existingWalls.Length > 0)
- {
- Debug.Log($"Successfully found and added {existingWalls.Length} pre-tagged walls from InitialRoomSetup");
- return;
- }
- // Fallback: Look for objects that should be walls but aren't tagged yet
- GameObject[] allObjects = FindObjectsByType<GameObject>(FindObjectsSortMode.None);
- int fixedWalls = 0;
- Debug.Log($"No pre-tagged walls found. Scanning {allObjects.Length} objects for potential walls...");
- foreach (GameObject obj in allObjects)
- {
- // Skip door components and other non-wall objects
- if (obj.name.Contains("Post") || obj.name.Contains("Beam") || obj.name.Contains("Door") ||
- obj.name.Contains("Mat") || obj.name.Contains("Entrance") || obj.name.Contains("Frame"))
- {
- continue;
- }
- // Look for specific wall naming patterns from InitialRoomSetup
- bool isInitialRoomWall = obj.name.Contains("North Wall") || obj.name.Contains("South Wall") ||
- obj.name.Contains("East Wall") || obj.name.Contains("West Wall");
- // Also check for other wall patterns
- bool isWallObject = obj.name.Contains("Wall") ||
- obj.name.Contains("wall") ||
- obj.name.StartsWith("Room") ||
- obj.name.Contains("Interior");
- if ((isInitialRoomWall || isWallObject) && !obj.CompareTag("Wall"))
- {
- // Additional check: make sure it has a collider (walls should have colliders)
- if (obj.GetComponent<Collider>() != null || obj.GetComponentInChildren<Collider>() != null)
- {
- Debug.Log($"Found untagged wall: {obj.name} - Scale: {obj.transform.localScale}, Position: {obj.transform.position}");
- obj.tag = "Wall";
- fixedWalls++;
- Debug.Log($"Fixed wall tag for: {obj.name}");
- // Also add it to our walls list
- if (!walls.Contains(obj))
- {
- walls.Add(obj);
- Debug.Log($"Added newly tagged wall to tracking: {obj.name}");
- }
- }
- }
- }
- if (fixedWalls > 0)
- {
- Debug.Log($"Fixed {fixedWalls} existing walls that weren't properly tagged");
- }
- else
- {
- Debug.Log("No walls found at all. This might indicate InitialRoomSetup hasn't run or there's a scene setup issue.");
- // Debug: List some objects to see what's in the scene
- Debug.Log("Sample objects in scene:");
- for (int i = 0; i < Mathf.Min(20, allObjects.Length); i++)
- {
- if (allObjects[i].name.Contains("Wall") || allObjects[i].name.Contains("wall") ||
- allObjects[i].transform.localScale.y > 2f)
- {
- Debug.Log($" Potential wall: {allObjects[i].name} - Scale: {allObjects[i].transform.localScale} - Tag: {allObjects[i].tag}");
- }
- }
- }
- }
- private void EnsurePrefabsExist()
- {
- // Create basic prefabs if they don't exist
- if (wallPrefab == null)
- {
- wallPrefab = CreateWallPrefab();
- Debug.Log("Created wall prefab dynamically");
- }
- if (wallPointPrefab == null)
- {
- wallPointPrefab = CreateWallPointPrefab();
- Debug.Log("Created wall point prefab dynamically");
- }
- if (doorOpeningPrefab == null)
- {
- doorOpeningPrefab = CreateDoorOpeningPrefab();
- Debug.Log("Created door opening prefab dynamically");
- }
- }
- #region Prefab Creation
- private GameObject CreateWallPrefab()
- {
- // Create a parent GameObject for the wall
- GameObject wall = new GameObject("Wall_Prefab");
- // Add a cube as child for the visual representation
- GameObject wallMesh = GameObject.CreatePrimitive(PrimitiveType.Cube);
- wallMesh.name = "WallMesh";
- wallMesh.transform.SetParent(wall.transform);
- wallMesh.transform.localPosition = Vector3.zero;
- wallMesh.transform.localRotation = Quaternion.identity;
- wallMesh.transform.localScale = Vector3.one;
- // Set up the wall material
- Renderer renderer = wallMesh.GetComponent<Renderer>();
- Material wallMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- // Set up proper wall color - light gray/beige
- wallMaterial.color = new Color(0.9f, 0.9f, 0.8f); // Light beige/cream color
- // Make sure it's not metallic and has proper smoothness
- wallMaterial.SetFloat("_Metallic", 0.0f);
- wallMaterial.SetFloat("_Smoothness", 0.2f);
- renderer.material = wallMaterial;
- // Ensure the wall has a collider for door placement detection
- BoxCollider collider = wallMesh.GetComponent<BoxCollider>();
- if (collider == null)
- {
- collider = wallMesh.AddComponent<BoxCollider>();
- }
- wall.tag = "Wall";
- // Don't destroy this object, keep it for instantiation
- DontDestroyOnLoad(wall);
- wall.SetActive(false); // Hide the template
- return wall;
- }
- private GameObject CreateWallPointPrefab()
- {
- // Create a parent GameObject for the wall point
- GameObject point = new GameObject("WallPoint_Prefab");
- // Add a sphere as child for the visual representation
- GameObject pointMesh = GameObject.CreatePrimitive(PrimitiveType.Sphere);
- pointMesh.name = "PointMesh";
- pointMesh.transform.SetParent(point.transform);
- pointMesh.transform.localPosition = Vector3.zero;
- pointMesh.transform.localRotation = Quaternion.identity;
- pointMesh.transform.localScale = Vector3.one * 0.2f;
- Renderer renderer = pointMesh.GetComponent<Renderer>();
- Material pointMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- // Set up bright red color for wall points
- pointMaterial.color = Color.red;
- pointMaterial.SetFloat("_Metallic", 0.0f);
- pointMaterial.SetFloat("_Smoothness", 0.8f); // Make it a bit shinier for visibility
- renderer.material = pointMaterial;
- // Remove collider to prevent interference
- Collider collider = pointMesh.GetComponent<Collider>();
- if (collider != null) DestroyImmediate(collider);
- DontDestroyOnLoad(point);
- point.SetActive(false); // Hide the template
- return point;
- }
- private GameObject CreateDoorOpeningPrefab()
- {
- // Create a parent GameObject for the door frame (visible part)
- GameObject door = new GameObject("DoorOpening_Prefab");
- // Create door frame - just the frame, not a solid door
- GameObject doorFrame = new GameObject("DoorFrame");
- doorFrame.transform.SetParent(door.transform);
- // Create frame components: left post, right post, top beam
- // Posts should be positioned at ground level with proper Y positioning
- CreateDoorFramePost(doorFrame, "LeftPost", new Vector3(-doorWidth / 2f, doorHeight / 2f, 0f));
- CreateDoorFramePost(doorFrame, "RightPost", new Vector3(doorWidth / 2f, doorHeight / 2f, 0f));
- CreateDoorFrameBeam(doorFrame, "TopBeam", new Vector3(0f, doorHeight - 0.1f, 0f));
- door.tag = "Door";
- DontDestroyOnLoad(door);
- return door;
- }
- private void CreateDoorFramePost(GameObject parent, string name, Vector3 position)
- {
- GameObject post = GameObject.CreatePrimitive(PrimitiveType.Cube);
- post.name = name;
- post.transform.SetParent(parent.transform);
- post.transform.localPosition = position;
- post.transform.localScale = new Vector3(0.1f, doorHeight, 0.2f); // Thin post
- Renderer renderer = post.GetComponent<Renderer>();
- Material frameMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- frameMaterial.color = new Color(0.4f, 0.2f, 0.1f); // Brown wood
- frameMaterial.SetFloat("_Metallic", 0.0f);
- frameMaterial.SetFloat("_Smoothness", 0.3f);
- renderer.material = frameMaterial;
- }
- private void CreateDoorFrameBeam(GameObject parent, string name, Vector3 position)
- {
- GameObject beam = GameObject.CreatePrimitive(PrimitiveType.Cube);
- beam.name = name;
- beam.transform.SetParent(parent.transform);
- beam.transform.localPosition = position;
- beam.transform.localScale = new Vector3(doorWidth + 0.2f, 0.2f, 0.2f); // Wide beam across top
- Renderer renderer = beam.GetComponent<Renderer>();
- Material frameMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- frameMaterial.color = new Color(0.4f, 0.2f, 0.1f); // Brown wood
- frameMaterial.SetFloat("_Metallic", 0.0f);
- frameMaterial.SetFloat("_Smoothness", 0.3f);
- renderer.material = frameMaterial;
- }
- #endregion
- #region Main Update Loop
- private void Update()
- {
- switch (currentMode)
- {
- case BuildingUIController.BuildingMode.CreatingWalls:
- HandleWallCreation();
- break;
- case BuildingUIController.BuildingMode.CreatingDoors:
- HandleDoorPlacement();
- break;
- case BuildingUIController.BuildingMode.CreatingEntrance:
- HandleEntranceCreation();
- break;
- default:
- HandleNormalMode();
- HideAllPreviews();
- break;
- }
- }
- public void SetBuildingMode(BuildingUIController.BuildingMode mode)
- {
- // Cancel any current wall creation
- if (isCreatingWall)
- {
- CancelWallCreation();
- }
- currentMode = mode;
- HideAllPreviews();
- Debug.Log($"Building mode changed to: {mode}");
- }
- #endregion
- #region Normal Mode
- private void HandleNormalMode()
- {
- // In normal mode, allow deletion of entrances with right-click
- if (Input.GetMouseButtonDown(1)) // Right click
- {
- Vector3 mousePos = GetMouseWorldPosition();
- CheckForEntranceDeletion(mousePos);
- }
- }
- private void CheckForEntranceDeletion(Vector3 mousePos)
- {
- Ray ray = playerCamera.ScreenPointToRay(Input.mousePosition);
- if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
- {
- GameObject hitObj = hit.collider.gameObject;
- // Check if we hit an entrance or entrance component
- GameObject entranceToDelete = null;
- if (hitObj.CompareTag("Entrance"))
- {
- entranceToDelete = hitObj;
- }
- else if (hitObj.transform.parent != null && hitObj.transform.parent.CompareTag("Entrance"))
- {
- entranceToDelete = hitObj.transform.parent.gameObject;
- }
- if (entranceToDelete != null)
- {
- Debug.Log($"Deleting entrance: {entranceToDelete.name}");
- DestroyImmediate(entranceToDelete);
- // Note: The wall segments around the entrance will remain
- // This creates a permanent opening where the entrance was
- }
- }
- }
- #endregion
- #region Wall Creation
- private void HandleWallCreation()
- {
- Vector3 mousePos = GetMouseWorldPosition();
- if (Input.GetMouseButtonDown(0)) // Left click
- {
- if (!isCreatingWall)
- {
- // Start creating a wall
- StartWallCreation(mousePos);
- }
- else
- {
- // Finish creating the wall
- FinishWallCreation(mousePos);
- }
- }
- else if (Input.GetMouseButtonDown(1)) // Right click
- {
- // Cancel wall creation
- if (isCreatingWall)
- {
- CancelWallCreation();
- }
- }
- // Update preview while creating wall
- if (isCreatingWall)
- {
- UpdateWallPreview(mousePos);
- }
- }
- private void StartWallCreation(Vector3 startPoint)
- {
- // Snap to nearby existing points
- Vector3 snappedStart = SnapToNearbyPoint(startPoint);
- wallStartPoint = snappedStart;
- isCreatingWall = true;
- // Show preview
- if (previewLine != null)
- {
- previewLine.enabled = true;
- }
- Debug.Log($"Started wall creation at: {wallStartPoint}");
- }
- private void UpdateWallPreview(Vector3 currentMousePos)
- {
- if (!isCreatingWall || previewLine == null) return;
- // Calculate snapped end point
- Vector3 snappedEndPoint = SnapToAngle(wallStartPoint, currentMousePos);
- Vector3 finalSnappedPoint = SnapToNearbyPoint(snappedEndPoint);
- // Show snap indicator if we're snapping to something
- if (Vector3.Distance(finalSnappedPoint, snappedEndPoint) > 0.1f)
- {
- ShowSnapIndicator(finalSnappedPoint);
- }
- else
- {
- HideSnapIndicator();
- }
- // Update preview line
- previewLine.SetPosition(0, wallStartPoint);
- previewLine.SetPosition(1, finalSnappedPoint);
- }
- private void ShowSnapIndicator(Vector3 position)
- {
- if (snapIndicator != null)
- {
- snapIndicator.transform.position = position;
- snapIndicator.SetActive(true);
- }
- }
- private void HideSnapIndicator()
- {
- if (snapIndicator != null)
- {
- snapIndicator.SetActive(false);
- }
- }
- private void FinishWallCreation(Vector3 endPoint)
- {
- if (!isCreatingWall) return;
- // Calculate snapped end point
- Vector3 snappedEndPoint = SnapToAngle(wallStartPoint, endPoint);
- snappedEndPoint = SnapToNearbyPoint(snappedEndPoint);
- // Create the actual wall
- CreateWall(wallStartPoint, snappedEndPoint);
- // Reset state
- isCreatingWall = false;
- if (previewLine != null)
- {
- previewLine.enabled = false;
- }
- Debug.Log($"Created wall from {wallStartPoint} to {snappedEndPoint}");
- }
- private void CancelWallCreation()
- {
- isCreatingWall = false;
- if (previewLine != null)
- {
- previewLine.enabled = false;
- }
- Debug.Log("Wall creation cancelled");
- }
- private Vector3 SnapToAngle(Vector3 startPoint, Vector3 endPoint)
- {
- Vector3 direction = (endPoint - startPoint).normalized;
- float distance = Vector3.Distance(startPoint, endPoint);
- // Calculate angle in degrees
- float currentAngle = Mathf.Atan2(direction.z, direction.x) * Mathf.Rad2Deg;
- if (currentAngle < 0) currentAngle += 360f;
- // Find closest snap angle
- float closestAngle = snapAngles[0];
- float smallestDifference = Mathf.Abs(currentAngle - closestAngle);
- foreach (float angle in snapAngles)
- {
- float difference = Mathf.Abs(currentAngle - angle);
- if (difference > 180f) difference = 360f - difference; // Handle wrapping
- if (difference < smallestDifference)
- {
- smallestDifference = difference;
- closestAngle = angle;
- }
- }
- // Calculate snapped direction
- float rad = closestAngle * Mathf.Deg2Rad;
- Vector3 snappedDirection = new Vector3(Mathf.Cos(rad), 0f, Mathf.Sin(rad));
- return startPoint + snappedDirection * distance;
- }
- private Vector3 SnapToNearbyPoint(Vector3 point)
- {
- float closestCornerDistance = float.MaxValue;
- float closestWallDistance = float.MaxValue;
- Vector3 closestCornerPoint = point;
- Vector3 closestWallPoint = point;
- bool foundCorner = false;
- foreach (GameObject wall in walls)
- {
- if (wall == null) continue;
- // First priority: Check both endpoints of the wall (corners)
- Vector3[] endpoints = GetWallEndpoints(wall);
- foreach (Vector3 endpoint in endpoints)
- {
- float distance = Vector3.Distance(point, endpoint);
- if (distance < snapDistance && distance < closestCornerDistance)
- {
- closestCornerDistance = distance;
- closestCornerPoint = endpoint;
- foundCorner = true;
- Debug.Log($"Found corner snap point at {endpoint}, distance: {distance}");
- }
- }
- // Second priority: Check snapping to wall surface/center (only if no corner found nearby)
- if (!foundCorner || closestCornerDistance > snapDistance * 0.7f) // Allow wall snapping if no close corner
- {
- Vector3 wallCenter = wall.transform.position;
- wallCenter.y = 0f; // Project to ground level
- // Project point onto wall line to find closest point on wall
- Vector3 wallDirection = wall.transform.forward;
- Vector3 toPoint = point - wallCenter;
- float projection = Vector3.Dot(toPoint, wallDirection);
- // Clamp projection to wall bounds
- float wallLength = wall.transform.localScale.z;
- projection = Mathf.Clamp(projection, -wallLength / 2f, wallLength / 2f);
- Vector3 closestPointOnWall = wallCenter + wallDirection * projection;
- float wallDistance = Vector3.Distance(point, closestPointOnWall);
- // Snap to wall surface if clicking near the wall
- if (wallDistance < snapDistance && wallDistance < closestWallDistance)
- {
- closestWallDistance = wallDistance;
- closestWallPoint = closestPointOnWall;
- Debug.Log($"Found wall surface snap point at {closestPointOnWall}, distance: {wallDistance}");
- }
- }
- }
- // Return the best snap point: prioritize corners over wall surfaces
- if (foundCorner && closestCornerDistance < snapDistance)
- {
- Debug.Log($"Using corner snap point: {closestCornerPoint}");
- UpdateSnapIndicatorColor(true); // Corner = cyan
- return closestCornerPoint;
- }
- else if (closestWallDistance < snapDistance)
- {
- Debug.Log($"Using wall surface snap point: {closestWallPoint}");
- UpdateSnapIndicatorColor(false); // Wall surface = yellow
- return closestWallPoint;
- }
- Debug.Log($"No snap point found, using original point: {point}");
- return point;
- }
- private void UpdateSnapIndicatorColor(bool isCorner)
- {
- if (snapIndicator != null)
- {
- Renderer renderer = snapIndicator.GetComponent<Renderer>();
- if (renderer != null)
- {
- Color indicatorColor = isCorner ? Color.cyan : Color.yellow;
- Color emissionColor = indicatorColor * 2f;
- renderer.material.color = indicatorColor;
- renderer.material.SetColor("_EmissionColor", emissionColor);
- }
- }
- }
- private void CreateWall(Vector3 startPoint, Vector3 endPoint)
- {
- if (Vector3.Distance(startPoint, endPoint) < 0.1f) return; // Too short
- // Calculate wall properties
- Vector3 center = (startPoint + endPoint) / 2f;
- center.y = wallHeight / 2f; // Set proper height
- Vector3 direction = (endPoint - startPoint).normalized;
- float length = Vector3.Distance(startPoint, endPoint);
- // Create wall object from prefab
- GameObject wall = Instantiate(wallPrefab, center, Quaternion.LookRotation(direction, Vector3.up));
- wall.SetActive(true); // Make sure it's visible
- // Scale the entire wall object to proper dimensions:
- // X = thickness (perpendicular to wall direction)
- // Y = height (up/down)
- // Z = length (along the wall direction)
- wall.transform.localScale = new Vector3(wallThickness, wallHeight, length);
- // Set wall name and add to list
- wall.name = $"Wall_{walls.Count}";
- walls.Add(wall);
- Debug.Log($"Created wall: {wall.name} from {startPoint} to {endPoint}, length: {length}");
- }
- #endregion
- #region Door Placement
- private void HandleDoorPlacement()
- {
- Vector3 mousePos = GetMouseWorldPosition();
- // Find wall under mouse
- GameObject wallUnderMouse = FindWallUnderMouse(mousePos);
- // Update hover preview
- UpdateDoorPreview(wallUnderMouse, mousePos);
- if (Input.GetMouseButtonDown(0)) // Left click
- {
- Debug.Log($"Door placement click detected at {mousePos}");
- if (wallUnderMouse != null)
- {
- Debug.Log($"Wall found under mouse: {wallUnderMouse.name}");
- PlaceDoorOnWall(wallUnderMouse, mousePos);
- }
- else
- {
- Debug.LogWarning("No wall found under mouse cursor for door placement");
- // Let's try a different approach - check nearby walls
- GameObject nearestWall = FindNearestWall(mousePos);
- if (nearestWall != null)
- {
- Debug.Log($"Found nearest wall: {nearestWall.name}, placing door there");
- PlaceDoorOnWall(nearestWall, mousePos);
- }
- else
- {
- Debug.LogWarning("No walls found nearby for door placement");
- }
- }
- }
- }
- private void UpdateDoorPreview(GameObject wall, Vector3 mousePos)
- {
- if (wall != hoveredWall)
- {
- hoveredWall = wall;
- if (wall != null)
- {
- ShowDoorPreview(wall, mousePos);
- }
- else
- {
- HideDoorPreview();
- }
- }
- else if (wall != null)
- {
- // Update preview position
- ShowDoorPreview(wall, mousePos);
- }
- }
- private void ShowDoorPreview(GameObject wall, Vector3 mousePos)
- {
- if (doorPreview == null) return;
- // Calculate door position on the wall
- Vector3 doorPosition = CalculateDoorPositionOnWall(wall, mousePos);
- // Position and orient the preview - door should face perpendicular to wall
- doorPreview.transform.position = doorPosition;
- doorPreview.transform.rotation = Quaternion.LookRotation(wall.transform.right);
- doorPreview.SetActive(true);
- }
- private void HideDoorPreview()
- {
- if (doorPreview != null)
- {
- doorPreview.SetActive(false);
- }
- }
- private void PlaceDoorOnWall(GameObject wall, Vector3 mousePos)
- {
- Debug.Log($"Attempting to place door on {wall.name} at mouse position {mousePos}");
- // Calculate door position
- Vector3 doorPosition = CalculateDoorPositionOnWall(wall, mousePos);
- Debug.Log($"Calculated door position: {doorPosition}");
- // Check if door would intersect with existing doors
- if (WouldDoorIntersectExistingDoors(wall, doorPosition))
- {
- Debug.LogWarning("Cannot place door - would intersect with existing door");
- return;
- }
- // Get wall endpoints and direction for splitting
- Vector3[] wallEndpoints = GetWallEndpoints(wall);
- Vector3 wallStart = wallEndpoints[0];
- Vector3 wallEnd = wallEndpoints[1];
- Vector3 wallDirection = wall.transform.forward;
- // Calculate door boundaries along the wall
- Vector3 doorStart = doorPosition - wallDirection * (doorWidth / 2f);
- Vector3 doorEnd = doorPosition + wallDirection * (doorWidth / 2f);
- // Create door at wall position with proper rotation
- // Door should face perpendicular to the wall direction (reuse existing wallDirection)
- Quaternion doorRotation = Quaternion.LookRotation(wall.transform.right); // Face perpendicular to wall
- GameObject door = Instantiate(doorOpeningPrefab, doorPosition, doorRotation);
- door.SetActive(true);
- door.name = $"Door_on_{wall.name}";
- // Split the original wall into two segments around the door
- SplitWallAroundDoor(wall, wallStart, wallEnd, doorStart, doorEnd);
- Debug.Log($"Successfully placed door: {door.name} and split wall into segments");
- }
- private bool WouldDoorIntersectExistingDoors(GameObject wall, Vector3 doorPosition)
- {
- // Find all existing doors
- GameObject[] existingDoors = GameObject.FindGameObjectsWithTag("Door");
- foreach (GameObject existingDoor in existingDoors)
- {
- // Check if doors are on the same wall or parallel walls
- float distance = Vector3.Distance(doorPosition, existingDoor.transform.position);
- if (distance < doorWidth * 1.5f) // Doors too close
- {
- Debug.Log($"Door too close to existing door {existingDoor.name}: distance = {distance}");
- return true;
- }
- }
- return false;
- }
- private void SplitWallAroundDoor(GameObject originalWall, Vector3 wallStart, Vector3 wallEnd, Vector3 doorStart, Vector3 doorEnd)
- {
- // Calculate the two new wall segments
- float originalWallLength = Vector3.Distance(wallStart, wallEnd);
- float leftSegmentLength = Vector3.Distance(wallStart, doorStart);
- float rightSegmentLength = Vector3.Distance(doorEnd, wallEnd);
- // Only create segments if they're long enough
- bool createLeftSegment = leftSegmentLength > 0.1f;
- bool createRightSegment = rightSegmentLength > 0.1f;
- Debug.Log($"Splitting wall: original length = {originalWallLength}, left = {leftSegmentLength}, right = {rightSegmentLength}");
- if (createLeftSegment)
- {
- // Create left wall segment - full height
- Vector3 leftCenter = (wallStart + doorStart) / 2f;
- leftCenter.y = wallHeight / 2f;
- GameObject leftWall = Instantiate(wallPrefab, leftCenter, originalWall.transform.rotation);
- leftWall.SetActive(true);
- leftWall.name = $"{originalWall.name}_Left";
- leftWall.transform.localScale = new Vector3(wallThickness, wallHeight, leftSegmentLength);
- walls.Add(leftWall);
- Debug.Log($"Created left wall segment: {leftWall.name}");
- }
- if (createRightSegment)
- {
- // Create right wall segment - full height
- Vector3 rightCenter = (doorEnd + wallEnd) / 2f;
- rightCenter.y = wallHeight / 2f;
- GameObject rightWall = Instantiate(wallPrefab, rightCenter, originalWall.transform.rotation);
- rightWall.SetActive(true);
- rightWall.name = $"{originalWall.name}_Right";
- rightWall.transform.localScale = new Vector3(wallThickness, wallHeight, rightSegmentLength);
- walls.Add(rightWall);
- Debug.Log($"Created right wall segment: {rightWall.name}");
- }
- // Create header beam above the door (if there are segments on both sides)
- if (createLeftSegment && createRightSegment)
- {
- CreateDoorHeaderBeam(originalWall, doorStart, doorEnd);
- }
- // Remove original wall from list and destroy it
- walls.Remove(originalWall);
- DestroyImmediate(originalWall);
- Debug.Log("Removed original wall after splitting");
- }
- private void CreateDoorHeaderBeam(GameObject originalWall, Vector3 doorStart, Vector3 doorEnd)
- {
- // Create beam above door opening
- Vector3 beamCenter = (doorStart + doorEnd) / 2f;
- beamCenter.y = doorHeight + 0.1f; // Just above the door
- GameObject headerBeam = Instantiate(wallPrefab, beamCenter, originalWall.transform.rotation);
- headerBeam.SetActive(true);
- headerBeam.name = $"{originalWall.name}_Header";
- float beamLength = Vector3.Distance(doorStart, doorEnd);
- float beamHeight = wallHeight - doorHeight - 0.1f; // Remaining height above door
- if (beamHeight > 0.1f) // Only create beam if there's significant height remaining
- {
- headerBeam.transform.localScale = new Vector3(wallThickness, beamHeight, beamLength);
- walls.Add(headerBeam);
- Debug.Log($"Created door header beam: {headerBeam.name}");
- }
- else
- {
- // If no room for header beam, destroy it
- DestroyImmediate(headerBeam);
- Debug.Log("Door is full height - no header beam needed");
- }
- }
- #endregion
- #region Entrance Creation
- private void HandleEntranceCreation()
- {
- Vector3 mousePos = GetMouseWorldPosition();
- // Find wall under mouse
- GameObject wallUnderMouse = FindWallUnderMouse(mousePos);
- // Update entrance preview (similar to door but different style)
- UpdateEntrancePreview(wallUnderMouse, mousePos);
- if (Input.GetMouseButtonDown(0)) // Left click
- {
- Debug.Log($"Entrance placement click detected at {mousePos}");
- if (wallUnderMouse != null)
- {
- Debug.Log($"Wall found under mouse: {wallUnderMouse.name}");
- PlaceEntranceOnWall(wallUnderMouse, mousePos);
- }
- else
- {
- Debug.LogWarning("No wall found under mouse cursor for entrance placement");
- // Try alternative detection method first
- GameObject alternativeWall = FindWallUnderMouseAlternative(mousePos);
- if (alternativeWall != null)
- {
- Debug.Log($"Alternative method found wall: {alternativeWall.name}, placing entrance there");
- PlaceEntranceOnWall(alternativeWall, mousePos);
- }
- else
- {
- // Let's try a different approach - check nearby walls
- GameObject nearestWall = FindNearestWall(mousePos);
- if (nearestWall != null)
- {
- Debug.Log($"Found nearest wall: {nearestWall.name}, placing entrance there");
- PlaceEntranceOnWall(nearestWall, mousePos);
- }
- else
- {
- Debug.LogWarning("No walls found nearby for entrance placement");
- }
- }
- }
- }
- }
- private void UpdateEntrancePreview(GameObject wall, Vector3 mousePos)
- {
- if (wall != null)
- {
- ShowEntrancePreview(wall, mousePos);
- }
- else
- {
- HideEntrancePreview();
- }
- }
- private void ShowEntrancePreview(GameObject wall, Vector3 mousePos)
- {
- if (doorPreview == null) return; // Reuse door preview for now
- // Calculate entrance position on the wall
- Vector3 entrancePosition = CalculateDoorPositionOnWall(wall, mousePos);
- // Position and orient the preview - entrance should face perpendicular to wall
- doorPreview.transform.position = entrancePosition;
- doorPreview.transform.rotation = Quaternion.LookRotation(wall.transform.right);
- // Make entrance preview slightly different (maybe different scale or color)
- doorPreview.transform.localScale = new Vector3(0.2f, doorHeight, doorWidth * 1.2f); // Slightly wider
- doorPreview.SetActive(true);
- }
- private void HideEntrancePreview()
- {
- if (doorPreview != null)
- {
- doorPreview.SetActive(false);
- }
- }
- private void PlaceEntranceOnWall(GameObject wall, Vector3 mousePos)
- {
- Debug.Log($"Attempting to place entrance on {wall.name} at mouse position {mousePos}");
- // Calculate entrance position on the wall surface
- Vector3 entrancePosition = CalculateDoorPositionOnWall(wall, mousePos);
- Debug.Log($"Calculated entrance position: {entrancePosition}");
- // Check if there's already an entrance
- GameObject[] existingEntrances = GameObject.FindGameObjectsWithTag("Entrance");
- if (existingEntrances.Length > 0)
- {
- Debug.LogWarning("Building already has an entrance. Replacing existing entrance.");
- foreach (GameObject existingEntrance in existingEntrances)
- {
- DestroyImmediate(existingEntrance);
- }
- }
- // Determine wall orientation based on its scale
- Vector3 wallScale = wall.transform.localScale;
- bool isNorthSouthWall = wallScale.x > wallScale.z; // Wide in X means North/South wall
- Debug.Log($"Wall scale: {wallScale}, isNorthSouthWall: {isNorthSouthWall}");
- // Calculate entrance boundaries and determine how to split the wall
- float entranceWidth = doorWidth * 1.5f;
- // Create entrance with proper rotation
- GameObject entrance = CreateEntrancePrefab();
- entrance.transform.position = entrancePosition;
- // Set rotation based on wall orientation
- if (isNorthSouthWall)
- {
- // For North/South walls (extending in X), entrance should face along Z-axis
- entrance.transform.rotation = Quaternion.identity; // Facing forward (positive Z)
- }
- else
- {
- // For East/West walls (extending in Z), entrance should face along X-axis
- entrance.transform.rotation = Quaternion.Euler(0, 90, 0); // Facing right (positive X)
- }
- entrance.SetActive(true);
- entrance.name = "BuildingEntrance";
- entrance.tag = "Entrance";
- Debug.Log($"Placed entrance at {entrance.transform.position} with rotation {entrance.transform.rotation.eulerAngles}");
- // Split the wall properly based on its orientation
- SplitWallForEntrance(wall, entrancePosition, entranceWidth, isNorthSouthWall);
- Debug.Log($"Successfully placed entrance and split wall");
- }
- private void SplitWallForEntrance(GameObject originalWall, Vector3 entrancePosition, float entranceWidth, bool isNorthSouthWall)
- {
- Vector3 wallPos = originalWall.transform.position;
- Vector3 wallScale = originalWall.transform.localScale;
- Quaternion wallRotation = originalWall.transform.rotation;
- // Get the original wall's material to maintain consistency
- Material originalMaterial = originalWall.GetComponent<Renderer>()?.material;
- Debug.Log($"Splitting wall: {originalWall.name} at position {wallPos} with scale {wallScale}");
- if (isNorthSouthWall)
- {
- // Wall extends in X direction, split along X-axis
- float wallLength = wallScale.x; // Corrected: X is the length for North/South walls
- float wallLeft = wallPos.x - wallLength / 2f;
- float wallRight = wallPos.x + wallLength / 2f;
- float entranceLeft = entrancePosition.x - entranceWidth / 2f;
- float entranceRight = entrancePosition.x + entranceWidth / 2f;
- Debug.Log($"North/South wall split: wallLeft={wallLeft}, wallRight={wallRight}, entranceLeft={entranceLeft}, entranceRight={entranceRight}");
- // Create left segment if there's enough space
- if (entranceLeft - wallLeft > 0.5f)
- {
- float leftLength = entranceLeft - wallLeft;
- Vector3 leftCenter = new Vector3(wallLeft + leftLength / 2f, wallPos.y, wallPos.z);
- GameObject leftWall = Instantiate(wallPrefab, leftCenter, wallRotation);
- leftWall.SetActive(true);
- leftWall.name = $"{originalWall.name}_Left_Entrance";
- leftWall.transform.localScale = new Vector3(leftLength, wallScale.y, wallScale.z);
- leftWall.tag = "Wall";
- // Apply original material if available
- if (originalMaterial != null)
- {
- leftWall.GetComponent<Renderer>().material = originalMaterial;
- }
- walls.Add(leftWall);
- Debug.Log($"Created left wall segment: scale {leftWall.transform.localScale} at {leftWall.transform.position}");
- }
- // Create right segment if there's enough space
- if (wallRight - entranceRight > 0.5f)
- {
- float rightLength = wallRight - entranceRight;
- Vector3 rightCenter = new Vector3(entranceRight + rightLength / 2f, wallPos.y, wallPos.z);
- GameObject rightWall = Instantiate(wallPrefab, rightCenter, wallRotation);
- rightWall.SetActive(true);
- rightWall.name = $"{originalWall.name}_Right_Entrance";
- rightWall.transform.localScale = new Vector3(rightLength, wallScale.y, wallScale.z);
- rightWall.tag = "Wall";
- // Apply original material if available
- if (originalMaterial != null)
- {
- rightWall.GetComponent<Renderer>().material = originalMaterial;
- }
- walls.Add(rightWall);
- Debug.Log($"Created right wall segment: scale {rightWall.transform.localScale} at {rightWall.transform.position}");
- }
- }
- else
- {
- // Wall extends in Z direction, split along Z-axis
- float wallLength = wallScale.z;
- float wallFront = wallPos.z - wallLength / 2f;
- float wallBack = wallPos.z + wallLength / 2f;
- float entranceFront = entrancePosition.z - entranceWidth / 2f;
- float entranceBack = entrancePosition.z + entranceWidth / 2f;
- Debug.Log($"East/West wall split: wallFront={wallFront}, wallBack={wallBack}, entranceFront={entranceFront}, entranceBack={entranceBack}");
- // Create front segment if there's enough space
- if (entranceFront - wallFront > 0.5f)
- {
- float frontLength = entranceFront - wallFront;
- Vector3 frontCenter = new Vector3(wallPos.x, wallPos.y, wallFront + frontLength / 2f);
- GameObject frontWall = Instantiate(wallPrefab, frontCenter, wallRotation);
- frontWall.SetActive(true);
- frontWall.name = $"{originalWall.name}_Front_Entrance";
- frontWall.transform.localScale = new Vector3(wallScale.x, wallScale.y, frontLength);
- frontWall.tag = "Wall";
- // Apply original material if available
- if (originalMaterial != null)
- {
- frontWall.GetComponent<Renderer>().material = originalMaterial;
- }
- walls.Add(frontWall);
- Debug.Log($"Created front wall segment: scale {frontWall.transform.localScale} at {frontWall.transform.position}");
- }
- // Create back segment if there's enough space
- if (wallBack - entranceBack > 0.5f)
- {
- float backLength = wallBack - entranceBack;
- Vector3 backCenter = new Vector3(wallPos.x, wallPos.y, entranceBack + backLength / 2f);
- GameObject backWall = Instantiate(wallPrefab, backCenter, wallRotation);
- backWall.SetActive(true);
- backWall.name = $"{originalWall.name}_Back_Entrance";
- backWall.transform.localScale = new Vector3(wallScale.x, wallScale.y, backLength);
- backWall.tag = "Wall";
- // Apply original material if available
- if (originalMaterial != null)
- {
- backWall.GetComponent<Renderer>().material = originalMaterial;
- }
- walls.Add(backWall);
- Debug.Log($"Created back wall segment: scale {backWall.transform.localScale} at {backWall.transform.position}");
- }
- }
- // Remove original wall
- walls.Remove(originalWall);
- DestroyImmediate(originalWall);
- Debug.Log("Removed original wall after splitting for entrance");
- }
- private GameObject CreateEntrancePrefab()
- {
- // Create a more elaborate entrance than a regular door
- GameObject entrance = new GameObject("BuildingEntrance");
- // Create entrance frame - wider and more elaborate
- GameObject entranceFrame = new GameObject("EntranceFrame");
- entranceFrame.transform.SetParent(entrance.transform);
- float entranceWidth = doorWidth * 1.5f;
- // Create frame components: left post, right post, top beam, and entrance mat
- CreateEntrancePost(entranceFrame, "LeftPost", new Vector3(-entranceWidth / 2f, doorHeight / 2f, 0f), entranceWidth);
- CreateEntrancePost(entranceFrame, "RightPost", new Vector3(entranceWidth / 2f, doorHeight / 2f, 0f), entranceWidth);
- CreateEntranceBeam(entranceFrame, "TopBeam", new Vector3(0f, doorHeight - 0.1f, 0f), entranceWidth);
- CreateEntranceMat(entranceFrame, "WelcomeMat", new Vector3(0f, 0.05f, 1f), entranceWidth);
- entrance.tag = "Entrance";
- DontDestroyOnLoad(entrance);
- return entrance;
- }
- private void CreateEntrancePost(GameObject parent, string name, Vector3 position, float width)
- {
- GameObject post = GameObject.CreatePrimitive(PrimitiveType.Cube);
- post.name = name;
- post.transform.SetParent(parent.transform);
- post.transform.localPosition = position;
- post.transform.localScale = new Vector3(0.15f, doorHeight, 0.3f); // Slightly thicker than door posts
- Renderer renderer = post.GetComponent<Renderer>();
- Material frameMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- frameMaterial.color = new Color(0.3f, 0.15f, 0.05f); // Darker brown for entrance
- frameMaterial.SetFloat("_Metallic", 0.0f);
- frameMaterial.SetFloat("_Smoothness", 0.4f);
- renderer.material = frameMaterial;
- }
- private void CreateEntranceBeam(GameObject parent, string name, Vector3 position, float width)
- {
- GameObject beam = GameObject.CreatePrimitive(PrimitiveType.Cube);
- beam.name = name;
- beam.transform.SetParent(parent.transform);
- beam.transform.localPosition = position;
- beam.transform.localScale = new Vector3(width + 0.3f, 0.3f, 0.3f); // Wider and thicker beam
- Renderer renderer = beam.GetComponent<Renderer>();
- Material frameMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- frameMaterial.color = new Color(0.3f, 0.15f, 0.05f); // Darker brown for entrance
- frameMaterial.SetFloat("_Metallic", 0.0f);
- frameMaterial.SetFloat("_Smoothness", 0.4f);
- renderer.material = frameMaterial;
- }
- private void CreateEntranceMat(GameObject parent, string name, Vector3 position, float width)
- {
- GameObject mat = GameObject.CreatePrimitive(PrimitiveType.Cube);
- mat.name = name;
- mat.transform.SetParent(parent.transform);
- mat.transform.localPosition = position;
- mat.transform.localScale = new Vector3(width, 0.1f, 1.5f); // Welcome mat dimensions
- Renderer renderer = mat.GetComponent<Renderer>();
- Material matMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- matMaterial.color = new Color(0.8f, 0.2f, 0.2f); // Red welcome mat
- matMaterial.SetFloat("_Metallic", 0.0f);
- matMaterial.SetFloat("_Smoothness", 0.1f); // Rough mat texture
- renderer.material = matMaterial;
- }
- #endregion
- #region Helper Methods
- private void CreatePreviewLine()
- {
- GameObject previewObj = new GameObject("WallPreview");
- previewLine = previewObj.AddComponent<LineRenderer>();
- // Use URP Unlit shader for line renderer (better for simple colored lines)
- previewLine.material = new Material(Shader.Find("Universal Render Pipeline/Unlit"));
- previewLine.material.color = Color.yellow;
- previewLine.startColor = Color.yellow;
- previewLine.endColor = Color.yellow;
- previewLine.startWidth = 0.1f;
- previewLine.endWidth = 0.1f;
- previewLine.positionCount = 2;
- previewLine.enabled = false;
- }
- private void CreateDoorPreview()
- {
- // Create a simple preview object
- doorPreview = GameObject.CreatePrimitive(PrimitiveType.Cube);
- doorPreview.name = "DoorPreview";
- // Make it transparent green
- Renderer renderer = doorPreview.GetComponent<Renderer>();
- Material previewMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- // Set up bright green transparent color
- previewMaterial.color = new Color(0f, 1f, 0f, 0.6f); // Bright transparent green
- // Set up transparency properly for URP
- previewMaterial.SetFloat("_Surface", 1); // Set to Transparent
- previewMaterial.SetFloat("_Blend", 0); // Alpha blend
- previewMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
- previewMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
- previewMaterial.SetInt("_ZWrite", 0);
- previewMaterial.renderQueue = 3000;
- // Make it non-metallic and smooth for better visibility
- previewMaterial.SetFloat("_Metallic", 0.0f);
- previewMaterial.SetFloat("_Smoothness", 0.9f);
- renderer.material = previewMaterial;
- // Scale to door size - match the actual door dimensions
- doorPreview.transform.localScale = new Vector3(0.2f, doorHeight, doorWidth);
- doorPreview.SetActive(false);
- // Remove collider to prevent interference
- Collider collider = doorPreview.GetComponent<Collider>();
- if (collider != null) Destroy(collider);
- }
- private void CreateSnapIndicator()
- {
- snapIndicator = GameObject.CreatePrimitive(PrimitiveType.Sphere);
- snapIndicator.name = "SnapIndicator";
- // Make it a bright, pulsing indicator
- Renderer renderer = snapIndicator.GetComponent<Renderer>();
- Material indicatorMaterial = new Material(Shader.Find("Universal Render Pipeline/Lit"));
- indicatorMaterial.color = Color.cyan;
- indicatorMaterial.SetFloat("_Metallic", 0.0f);
- indicatorMaterial.SetFloat("_Smoothness", 0.9f);
- // Make it emissive so it glows
- indicatorMaterial.EnableKeyword("_EMISSION");
- indicatorMaterial.SetColor("_EmissionColor", Color.cyan * 2f);
- renderer.material = indicatorMaterial;
- // Scale it to be visible but not too large
- snapIndicator.transform.localScale = Vector3.one * 0.3f;
- snapIndicator.SetActive(false);
- // Remove collider to prevent interference
- Collider collider = snapIndicator.GetComponent<Collider>();
- if (collider != null) Destroy(collider);
- }
- private void HideAllPreviews()
- {
- if (previewLine != null)
- {
- previewLine.enabled = false;
- }
- HideDoorPreview();
- HideSnapIndicator();
- }
- private Vector3 GetMouseWorldPosition()
- {
- Ray ray = playerCamera.ScreenPointToRay(Input.mousePosition);
- // Cast ray onto ground plane (Y = 0)
- if (Physics.Raycast(ray, out RaycastHit hit))
- {
- return hit.point;
- }
- // Fallback: project onto Y = 0 plane
- float distance = -ray.origin.y / ray.direction.y;
- return ray.origin + ray.direction * distance;
- }
- private GameObject FindWallUnderMouse(Vector3 mousePos)
- {
- Ray ray = playerCamera.ScreenPointToRay(Input.mousePosition);
- Debug.Log($"Raycasting for wall detection at mouse position: {Input.mousePosition}");
- Debug.Log($"Ray origin: {ray.origin}, Ray direction: {ray.direction}");
- Debug.Log($"Camera: {playerCamera?.name ?? "NULL"}, Camera position: {playerCamera?.transform.position ?? Vector3.zero}");
- Debug.Log($"Total walls in list: {walls.Count}");
- // Check if we have any walls with colliders
- int wallsWithColliders = 0;
- foreach (GameObject wall in walls)
- {
- if (wall != null)
- {
- Collider[] colliders = wall.GetComponentsInChildren<Collider>();
- if (colliders.Length > 0)
- {
- wallsWithColliders++;
- Debug.Log($"Wall {wall.name} has {colliders.Length} colliders");
- }
- }
- }
- Debug.Log($"Walls with colliders: {wallsWithColliders}");
- // Try raycasting with all layers first
- if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
- {
- GameObject hitObj = hit.collider.gameObject;
- Debug.Log($"Raycast hit object: {hitObj.name} on layer {hitObj.layer}");
- Debug.Log($"Hit point: {hit.point}, Hit distance: {hit.distance}");
- // Check if it's one of our walls (could be parent or child)
- GameObject wallToCheck = hitObj;
- // If we hit a child mesh, get the parent
- if (hitObj.name == "WallMesh" && hitObj.transform.parent != null)
- {
- wallToCheck = hitObj.transform.parent.gameObject;
- Debug.Log($"Hit child mesh, checking parent: {wallToCheck.name}");
- }
- if (walls.Contains(wallToCheck))
- {
- Debug.Log($"Hit object is a valid wall: {wallToCheck.name}");
- return wallToCheck;
- }
- else
- {
- Debug.Log($"Hit object is not a wall we created: {wallToCheck.name}");
- // Also check if the hit object has a Wall tag as fallback
- if (hitObj.CompareTag("Wall") || (hitObj.transform.parent != null && hitObj.transform.parent.CompareTag("Wall")))
- {
- GameObject taggedWall = hitObj.CompareTag("Wall") ? hitObj : hitObj.transform.parent.gameObject;
- Debug.Log($"Found wall by tag: {taggedWall.name}");
- return taggedWall;
- }
- }
- }
- else
- {
- Debug.Log("Raycast didn't hit anything - checking for potential issues:");
- Debug.Log($"PlayerCamera null? {playerCamera == null}");
- Debug.Log($"Physics.DefaultRaycastLayers: {Physics.DefaultRaycastLayers}");
- // Try a wider raycast with all layers
- RaycastHit[] hits = Physics.RaycastAll(ray, 1000f);
- Debug.Log($"RaycastAll found {hits.Length} hits");
- for (int i = 0; i < hits.Length; i++)
- {
- Debug.Log($"Hit {i}: {hits[i].collider.gameObject.name} on layer {hits[i].collider.gameObject.layer}");
- }
- }
- return null;
- }
- private GameObject FindWallUnderMouseAlternative(Vector3 worldMousePos)
- {
- // Alternative approach: find the closest wall to the mouse world position
- GameObject closestWall = null;
- float closestDistance = float.MaxValue;
- float maxDistance = 2f; // Maximum distance to consider a wall "under" the mouse
- Debug.Log($"Alternative wall detection at world pos: {worldMousePos}");
- foreach (GameObject wall in walls)
- {
- if (wall == null) continue;
- // Calculate distance from mouse world position to wall center
- float distance = Vector3.Distance(worldMousePos, wall.transform.position);
- // Also check distance to wall bounds
- Bounds wallBounds = GetWallBounds(wall);
- float boundDistance = wallBounds.SqrDistance(worldMousePos);
- Debug.Log($"Wall {wall.name}: center distance = {distance}, bound distance = {Mathf.Sqrt(boundDistance)}");
- if (boundDistance < maxDistance * maxDistance && distance < closestDistance)
- {
- closestDistance = distance;
- closestWall = wall;
- }
- }
- if (closestWall != null)
- {
- Debug.Log($"Alternative method found wall: {closestWall.name} at distance {closestDistance}");
- }
- else
- {
- Debug.Log("Alternative method found no walls nearby");
- }
- return closestWall;
- }
- private Bounds GetWallBounds(GameObject wall)
- {
- Renderer renderer = wall.GetComponentInChildren<Renderer>();
- if (renderer != null)
- {
- return renderer.bounds;
- }
- // Fallback: calculate bounds from transform
- Vector3 scale = wall.transform.localScale;
- return new Bounds(wall.transform.position, scale);
- }
- private GameObject FindNearestWall(Vector3 mousePos)
- {
- GameObject nearestWall = null;
- float nearestDistance = float.MaxValue;
- foreach (GameObject wall in walls)
- {
- if (wall == null) continue;
- // Calculate distance from mouse position to wall
- float distance = Vector3.Distance(mousePos, wall.transform.position);
- if (distance < nearestDistance && distance < 5f) // Within 5 units
- {
- nearestDistance = distance;
- nearestWall = wall;
- }
- }
- if (nearestWall != null)
- {
- Debug.Log($"Found nearest wall: {nearestWall.name} at distance {nearestDistance}");
- }
- return nearestWall;
- }
- private Vector3[] GetWallEndpoints(GameObject wall)
- {
- // Calculate endpoints from wall transform
- Vector3 center = wall.transform.position;
- // With our new rotation, the wall extends along the forward (Z) axis
- Vector3 wallDirection = wall.transform.forward;
- float length = wall.transform.localScale.z; // Z is now the length
- Vector3 start = center - wallDirection * (length / 2f);
- Vector3 end = center + wallDirection * (length / 2f);
- // Ensure Y = 0 for ground-level snapping
- start.y = 0f;
- end.y = 0f;
- return new Vector3[] { start, end };
- }
- private Vector3 CalculateDoorPositionOnWall(GameObject wall, Vector3 mousePos)
- {
- // Project mouse position onto the wall
- Vector3 wallCenter = wall.transform.position;
- Vector3 wallScale = wall.transform.localScale;
- // Determine wall orientation based on scale (not rotation)
- bool isNorthSouthWall = wallScale.x > wallScale.z;
- Vector3 wallDirection;
- float wallLength;
- if (isNorthSouthWall)
- {
- // Wall extends in X direction (North/South wall)
- wallDirection = Vector3.right;
- wallLength = wallScale.x;
- }
- else
- {
- // Wall extends in Z direction (East/West wall)
- wallDirection = Vector3.forward;
- wallLength = wallScale.z;
- }
- // Project mouse onto wall line
- Vector3 toMouse = mousePos - wallCenter;
- float projection = Vector3.Dot(toMouse, wallDirection);
- // Clamp to wall bounds
- projection = Mathf.Clamp(projection, -wallLength / 2f + doorWidth / 2f, wallLength / 2f - doorWidth / 2f);
- Vector3 doorPos = wallCenter + wallDirection * projection;
- doorPos.y = 0f; // Set door at ground level
- Debug.Log($"Door position calculation: wallCenter={wallCenter}, wallDirection={wallDirection}, projection={projection}, doorPos={doorPos}");
- return doorPos;
- }
- #endregion
- }
|