Ejemplo n.º 1
0
    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");
            }
        }
    }
Ejemplo n.º 2
0
        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);
                }
            }
        }