private void CheckGameCharacterState(Character character) { if (character.CharacterControlType == CharacterControlType.None) { return; } if (character.CharacterControlType == CharacterControlType.Player) { if (Characters.Count >= 1) { OnPlacementChange.Invoke(Characters.Count + 1); GameManager.Instance.CompilateStage(false); AnalitycsManager.Instance.LogEvent("Level_Event", "Level_Fail", Characters.Count.ToString()); Debug.Log("Player lose the geme"); } } else { if (Characters.Count <= 1) { GameManager.Instance.CompilateStage(true); Debug.Log("Player won the geme"); } } }
private void Update() { if (!Running) { return; } //apply volume scale: willFitVolume.transform.localScale = volume; willNotFitVolume.transform.localScale = volume; //evaluate surface: RaycastHit surfaceHit; //tilt cast vector: Quaternion adjustmentQuaternion = Quaternion.AngleAxis(tilt, _source.right); Vector3 castVector = adjustmentQuaternion * _source.forward; if (Physics.Raycast(_source.position, castVector, out surfaceHit, maxDistance)) { //feedback: Debug.DrawLine(_source.position, surfaceHit.point); //set initial position: Position = surfaceHit.point; //autosize: if (scaleVolumeWithDistance) { ScaleVolumeByDistance(); } //phase 1: surface validity Surface = GetSurfaceType(surfaceHit.normal); _fitStatus = SurfaceTypeCheck(Surface); //phase 2: corner evenness if (_fitStatus == FitType.Fits) { //get a "perfect" normal since meshing is not perfect: _yAxis = GetPerfectNormal(Surface, surfaceHit.normal); //find axis: Vector3 xAxis = GetCrossAxis(Surface, _yAxis); Vector3 zAxis = Vector3.Cross(_yAxis, xAxis); //set rotation: if (Surface == SurfaceType.Vertical && matchGravityOnVerticals) { Rotation = Quaternion.LookRotation(_yAxis, Vector3.up); } else { Rotation = Quaternion.LookRotation(zAxis, _yAxis); } //locate each surface-proximity corner: Vector3 halfVolume = volume * .5f; Vector3 cornerA = Vector3.zero; Vector3 cornerB = Vector3.zero; Vector3 cornerC = Vector3.zero; Vector3 cornerD = Vector3.zero; RaycastHit cornerAHit = new RaycastHit(); RaycastHit cornerBHit = new RaycastHit(); RaycastHit cornerCHit = new RaycastHit(); RaycastHit cornerDHit = new RaycastHit(); if (matchGravityOnVerticals && Surface == SurfaceType.Vertical) { cornerA = surfaceHit.point + (zAxis * -halfVolume.y) + (xAxis * -halfVolume.x); cornerB = surfaceHit.point + (zAxis * -halfVolume.y) + (xAxis * halfVolume.x); cornerC = surfaceHit.point + (zAxis * halfVolume.y) + (xAxis * halfVolume.x); cornerD = surfaceHit.point + (zAxis * halfVolume.y) + (xAxis * -halfVolume.x); //find corner-to-surface points: cornerAHit = CornerCast(_yAxis, cornerA, volume.z); cornerBHit = CornerCast(_yAxis, cornerB, volume.z); cornerCHit = CornerCast(_yAxis, cornerC, volume.z); cornerDHit = CornerCast(_yAxis, cornerD, volume.z); } else { cornerA = surfaceHit.point + (zAxis * halfVolume.z) + (xAxis * halfVolume.x); cornerB = surfaceHit.point + (zAxis * halfVolume.z) + (xAxis * -halfVolume.x); cornerC = surfaceHit.point + (zAxis * -halfVolume.z) + (xAxis * -halfVolume.x); cornerD = surfaceHit.point + (zAxis * -halfVolume.z) + (xAxis * halfVolume.x); //find corner-to-surface points: cornerAHit = CornerCast(_yAxis, cornerA, volume.y); cornerBHit = CornerCast(_yAxis, cornerB, volume.y); cornerCHit = CornerCast(_yAxis, cornerC, volume.y); cornerDHit = CornerCast(_yAxis, cornerD, volume.y); } //all corners have hit something: if (cornerAHit.collider != null && cornerBHit.collider != null && cornerCHit.collider != null && cornerDHit.collider != null) { //get evenness values: float cornerAEvenness = EvenSurfaceCheck(surfaceHit.point, cornerAHit.point, xAxis, zAxis); float cornerBEvenness = EvenSurfaceCheck(surfaceHit.point, cornerBHit.point, xAxis, zAxis); float cornerCEvenness = EvenSurfaceCheck(surfaceHit.point, cornerCHit.point, xAxis, zAxis); float cornerDEvenness = EvenSurfaceCheck(surfaceHit.point, cornerDHit.point, xAxis, zAxis); //are we within the maxUneven threshold? float largestBump = Mathf.Max(cornerAEvenness, cornerBEvenness, cornerCEvenness, cornerDEvenness); //determine if we passed evenness testing: if (largestBump > maxUneven) { _fitStatus = FitType.Uneven; } else { _fitStatus = FitType.Fits; Position = surfaceHit.point + (_yAxis * largestBump); } } else { //we are likely hanging over a physical edge: _fitStatus = FitType.Overhang; } //push out if we want to align with gravity while on a wall: if (matchGravityOnVerticals && Surface == SurfaceType.Vertical) { //out: Position += _yAxis * (volume.z * .5f); } } //phase 3: volume clearance if (_fitStatus == FitType.Fits) { //locate the center of our volume: Vector3 centerPoint = Position + (_yAxis * (volume.y * .5f)); //test a volume that is smaller than our actual volume by uneven allowance as a buffer: Vector3 collisionVolumeSize = volume * (.5f - maxUneven); //check for volume collisions: Collider[] volumeCollisions = Physics.OverlapBox(centerPoint, collisionVolumeSize, Rotation); //passed? if (volumeCollisions.Length > 0) { _fitStatus = FitType.VolumeIntersection; } else { _fitStatus = FitType.Fits; } } } else { //feedback: Debug.DrawRay(_source.position, castVector * maxDistance); //status: _fitStatus = FitType.NoSurface; //resets: Surface = SurfaceType.Unknown; Position = _source.position + (castVector * maxDistance); Rotation = Quaternion.LookRotation(-_source.forward); } bool customRuleResult = true; if (_customRule != null) { customRuleResult = _customRule(Position); } if (_fitStatus == FitType.Fits && customRuleResult) { //volume handling: willFitVolume.SetActive(true); willNotFitVolume.SetActive(false); } else { //volume handling: willFitVolume.SetActive(false); willNotFitVolume.SetActive(true); } //pose our volumes: if (_fitStatus == FitType.NoSurface) { willFitVolume.transform.position = Position; willNotFitVolume.transform.position = Position; willFitVolume.transform.rotation = Rotation; willNotFitVolume.transform.rotation = Rotation; } else { Vector3 finalLocation = Vector3.zero; if (matchGravityOnVerticals && Surface == SurfaceType.Vertical) { //finalLocation = Position + (_yAxis * Volume.z * .5f); finalLocation = Position; } else { finalLocation = Position + (_yAxis * volume.y * .5f); } willFitVolume.transform.position = finalLocation; willNotFitVolume.transform.position = finalLocation; willFitVolume.transform.rotation = Rotation; willNotFitVolume.transform.rotation = Rotation; } //broadcast status: if (Fit != _fitStatus) { Fit = _fitStatus; if (OnPlacementEvent != null) { OnPlacementEvent.Invoke(_fitStatus); } } }