//=================================================================================================================o // Check for ledge collider in front void CheckLedge() { if (hMove.Grounded) { RaycastHit hit; if (!Physics.Raycast(hero.position + hero.up, hero.forward, 1f, climbLayers)) { return; } else if (Physics.Raycast(hero.position + hero.up, hero.forward, out hit, 1f, climbLayers)) { if (hit.collider.name == "climbLedge") { isClimbing = true; rb.isKinematic = true; hMove.canMove = false; isLedgeEnd = false; curT = hit.transform; lastHeroPos = hero.position; if (doClimbDel != null) { doClimbDel("Ledge"); } climbState = ClimbState.LedgeJump; } } } }
//=================================================================================================================o // At corner change climb handle void CornerLerp(float speed) { Vector3 v = nextPoint - (hero.right * cornerSideOffset) - (hero.forward * offsetToWall) - (hero.up * heightOffsetToEdge); float angleTo = Vector3.Angle(hero.right, curT.transform.right); // Faster if angle is rel small speed = angleTo <= 15.0f ? speed *= 15 : speed *= 4; // Apply hero.position = Vector3.Lerp(hero.position, v, Time.deltaTime * speed); hero.rotation = Quaternion.Lerp(hero.rotation, curT.rotation, Time.deltaTime * speed); // Shift inward a bit if (angleTo <= 0.01f) { Vector3 relPoint = curT.InverseTransformPoint(hero.position); SmoothToSpot(Mathf.Abs(relPoint.z), offsetToWall, Vector3.forward, Vector3.back); if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; // Out } // Reset hang atHangR = false; atHangL = false; }
//=================================================================================================================o // Jump over ledge void LedgeJump() { Vector3 topVec = new Vector3(lastHeroPos.x, curT.position.y + 0.3f, lastHeroPos.z); Vector3 fwdVec = topVec + hero.forward * 2.0f; Vector3 dwnVec = hero.position - (hero.up * 3f); // Up if (((hero.position.y - curT.position.y) <= 0.0f) && !isLedgeEnd) { hero.position = Vector3.Lerp(hero.position, topVec, Time.deltaTime * climbSpeed * 5f); } else { // Forward if (!isLedgeEnd) { hero.position = Vector3.Lerp(hero.position, fwdVec, Time.deltaTime * climbSpeed * 9f); } // Down & Exit if (Vector3.Distance(topVec, hero.position) >= 1.8f) // Forward distance to go over the ledge { isLedgeEnd = true; hero.position = Vector3.Lerp(hero.position, dwnVec, Time.deltaTime * climbSpeed * 1.0f); if (hMove.Grounded) { climbState = ClimbState.None; } } } }
//=================================================================================================================o IEnumerator Prepare() { isPreparing = true; if (doClimbDel != null) { doClimbDel("Prepare"); } climbState = ClimbState.Prepare; yield return(new WaitForSeconds(0.9f)); if (Input.GetKey(KeyCode.E) && climbState == ClimbState.Prepare) // Climb up { if (doClimbDel != null) { doClimbDel("Climb"); } climbState = ClimbState.Climb; // Move to edge } else // Stay at position { isPullUp = false; isOverhang = false; yield return(new WaitForSeconds(0.2f)); // Fade to hang pose nextPoint = hero.position - ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); //Current position curT = lastT; climbState = ClimbState.Climb; // To last position } isPreparing = false; }
//=================================================================================================================o // Reset if leaving Climb modus public void ExitClimb() { rb.isKinematic = false; hMove.canMove = true; atHangR = false; atHangL = false; isWall = false; isPullUp = false; curT = null; lastT = null; rb.AddForce(Vector3.down * 2, ForceMode.VelocityChange); // Restore Rotation if (inClimbRot) { hero.rotation = Quaternion.Euler(0, rot.eulerAngles.y, 0); inClimbRot = false; } isClimbing = false; if (doClimbDel != null) { doClimbDel("None"); } climbState = ClimbState.None; // Out reset = true; }
//=================================================================================================================o void Start() { hero = transform; rb = rigidbody; climbState = ClimbState.None; Physics.IgnoreLayerCollision(8, 9); // ignore player / climb collision hMove = GetComponent <HeroMotor> () as HeroMotor; hSwim = GetComponent <HeroSwim> () as HeroSwim; cacheDist = checkDistance; }
protected override void CustomStartState() { foreach (var state in possibleNextStates) { ClimbState cs = state as ClimbState; if (cs) { nextClimbUpState = cs; break; } } }
//=================================================================================================================o // Wall climb handling void WallClimb() { Vector3 relV = curT.InverseTransformPoint(hero.position); float distY = Mathf.Abs(relV.y); float distZ = Mathf.Abs(relV.z); // Limit is almost the edge if (distY >= heightOffsetToEdge * 1.1f) { SmoothToSpot(distZ, offsetToWall, Vector3.forward, Vector3.back); // Input if (Input.GetAxis("Vertical") != 0.0f) { if (Input.GetAxis("Vertical") > 0.0f) { inputVec = hero.TransformPoint(Vector3.up); } else { inputVec = hero.TransformPoint(Vector3.down); if (!Physics.Raycast(hero.position, hero.forward, offsetToWall, climbLayers) || hMove.Grounded) { climbState = ClimbState.None; } } // Apply movement hero.position = Vector3.Lerp(hero.position, inputVec, Time.deltaTime * climbSpeed * 1.3f); } else // Stop if there's no input { inputVec = hero.TransformPoint(Vector3.zero); } } else // Reached the edge { if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; // Out } // Drop // Action key down to Exit if (Input.GetKeyDown(KeyCode.E) && !hMove.Grounded) { climbState = ClimbState.None; // Out } }
//=================================================================================================================o // Jump to next spot void WallJump() { if (hMove.Grounded) // Jump to wall { // if Grounded and edge is very close, just snap! if (Vector3.Distance(hero.position, nextPoint) <= 2.5f) { Climb(); } else // do a walljump { hero.Translate(hero.up * Time.deltaTime * climbSpeed * 8); } } else // Air/Edge { if (curT.name == "climbArea") { // Jump to position Vector3 edgePos = nextPoint + ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); // Apply lift up hero.position = Vector3.Lerp(hero.position, edgePos, Time.deltaTime * climbSpeed * 8); // 10 // At position if (Vector3.Distance(hero.position, edgePos) <= 0.1f) { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallClimb; // Out } } else if (curT.name == "climbWall") { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallClimb; // Out } else { Climb(); // Climb to --> Edge and Out } } }
void LookForClimbSpot() { Transform camTrans = Camera.main.transform; var ray = new Ray(camTrans.position, camTrans.forward); RaycastHit hit; LayerMask mask = ~((1 << gameObject.layer) | (1 << 3)); float maxDistance = 20; if (!Physics.Raycast(ray, out hit, maxDistance, mask)) { Debug.Log("No hit"); return; } Debug.Log(hit.transform.gameObject.name); var manager = hit.transform.GetComponent <GridManager>(); if (manager == null) { Debug.Log("No manager"); return; } var closestPoint = manager.GetClosestPoint(transform.position); float distance = Vector3.Distance(transform.position, closestPoint.transform.parent.position); if (distance > 5) { Debug.Log("Too great distance"); return; } _curManager = manager; _targetPoint = closestPoint; _targetPosition = closestPoint.transform.position; _curPoint = closestPoint; climbing = true; _lockInput = true; _targetState = ClimbState.onPoint; _anim.CrossFade("To_Climb", 0.4f); GetComponent <Controller.StateManager>().DisableController(); _waitToStartClimb = true; Debug.Log("All o kay"); }
void WallJump() { Debug.Log("Walljump"); Vector3 walljumpWay = Vector3.right; walljumpWay.y = Mathf.Tan(LastWallAngle - 180); walljumpWay.Normalize(); walljumpWay *= wallJumpForce.x; walljumpWay.y = wallJumpForce.y; MoveForce f = new MoveForce(walljumpWay, wallJumpGravity, wallJumpTime, 0.1f); forces.Add(f); wallClimb = ClimbState.Jumping; }
IEnumerator WrapUpTransition(float t) { yield return(new WaitForSeconds(t)); _climbState = _targetState; if (_climbState == ClimbState.onPoint) { _curPoint = _targetPoint; _anim.SetBool("Move", false); } _initTransit = false; _lockInput = false; _inputDirection = Vector3.zero; _waitForWrapUp = false; }
//=================================================================================================================o IEnumerator PreShort(ClimbState cS) { isPreShort = true; // Switch fast to next step if falling float seconds = climbState != ClimbState.None ? 0.75f : 0.0f; // Delegate to trigger animation state if (doClimbDel != null) { doClimbDel("PreShort"); } climbState = ClimbState.PreShort; // prepare for short distance climb (Animation) yield return(new WaitForSeconds(seconds)); if (Input.GetKey(KeyCode.E) && climbState == ClimbState.PreShort) // Climb up { if (doClimbDel != null) { doClimbDel("Short"); } climbState = cS; //ClimbState.Climb; // Move to edge } else // Stay at position { isPullUp = false; isOverhang = false; yield return(new WaitForSeconds(0.3f)); // Fade to hang pose if (curT != null && curT.name != "climbArea") { nextPoint = hero.position - ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); //lastPoint; curT = lastT; climbState = ClimbState.Climb; // To last } else // We hit a Wall collider start climbing { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallClimb; } } isPreShort = false; }
void OnPoint(Vector3 direction) { neighbour = _curPoint.GetNeighbour(direction); if (neighbour == null) { return; } _targetPoint = neighbour.target; _prevPoint = _curPoint; _climbState = ClimbState.inTransit; UpdateconnectionTransitByType(neighbour, direction); _lockInput = true; }
//=================================================================================================================o IEnumerator Overhang() { if (doClimbDel != null) { doClimbDel("Overhang"); } climbState = ClimbState.Overhang; yield return(new WaitForSeconds(2.2f)); if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; isOverhang = false; }
//public Animator _animator; void Awake() { //_animator = GetComponent<Animator>(); controller = GetComponent <CharacterController2D>(); controller.onControllerCollidedEvent += onControllerCollider; controller.onTriggerEnterEvent += onTriggerEnterEvent; controller.onTriggerExitEvent += onTriggerExitEvent; // initialize all states jumpState = new JumpState(this); runState = new RunState(this); idleState = new IdleState(this); climbState = new ClimbState(this); stealthState = new StealthState(this); // set beginning state SetMovementState(idleState); }
void InitClimbing() { if (_initClimb) { return; } _initClimb = true; if (_ik != null) { _ik.UpdateAllPointsOnOne(_targetPoint); _ik.UpdateAllTargetPositions(_targetPoint); _ik.ImmediatePlaceHelpers(); } curConnection = ConnectionType.direct; _targetState = ClimbState.onPoint; }
void HandleMount() { if (!_initTransit) { _initTransit = true; _ikFollowSideReached = false; _ikLandSideReached = false; _interpolT = 0; _interpolStart = transform.position; _interpolTarget = _targetPosition + rootOffset; _curCurve = _mountCurve; _curCurve.transform.rotation = _targetPoint.transform.rotation; var points = _curCurve.GetAnchorPoints(); points[0].transform.position = _interpolStart; points[points.Length - 1].transform.position = _interpolTarget; } if (enableRootMovement) { _interpolT += Time.deltaTime * 2; } if (_interpolT >= 1) { _interpolT = 1; _waitToStartClimb = false; _lockInput = false; _initTransit = false; _ikLandSideReached = false; _climbState = _targetState; } var targetPos = _curCurve.GetPointAt(_interpolT); Debug.DrawLine(transform.position, targetPos, Color.gray); Debug.DrawLine(transform.position, _interpolTarget, Color.black); transform.position = targetPos; HandleWeightAll(_interpolT, mountCurve); HandleRotation(); }
public override void Place() { base.Place(); LevelController = FindObjectOfType <LevelController>(); _stateMachine = new StateMachine(); _walkState = new WalkState(this); var fallState = new FallState(this); var climbState = new ClimbState(this); var dieState = new DieState(this); _stateMachine.AddTransition(_walkState, fallState, () => !OnGround); _stateMachine.AddTransition(fallState, _walkState, () => OnGround); _stateMachine.AddTransition(_walkState, climbState, () => Climbing); _stateMachine.AddTransition(climbState, _walkState, () => !Climbing); _stateMachine.AddAnyTransition(dieState, () => _dead); }
//=================================================================================================================o IEnumerator PreTop() { isPreparing = true; if (curT.name == "climbObjectTopOh") { if (doClimbDel != null) { doClimbDel("PreOh"); } // Overhang } else { if (doClimbDel != null) { doClimbDel("Prepare"); } // Normal } climbState = ClimbState.Prepare; yield return(new WaitForSeconds(0.8f)); if (Input.GetKey(KeyCode.E) && climbState == ClimbState.Prepare) // Climb up { if (doClimbDel != null) { doClimbDel("Top"); } climbState = ClimbState.Top; // Out } else // Stay at position { yield return(new WaitForSeconds(0.2f)); // Fade to hang pose if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; } isPreparing = false; }
void UpdateconnectionTransitByType(Neighbour n, Vector3 inputDirection) { var desiredPosition = Vector3.zero; curConnection = n.cType; Vector3 direction = _targetPoint.transform.position - _curPoint.transform.position; direction.Normalize(); switch (n.cType) { case ConnectionType.inBetween: var dist = Vector3.Distance(_curPoint.transform.position, _targetPoint.transform.position); desiredPosition = _curPoint.transform.position + (direction * (dist / 2)); _targetState = ClimbState.betweenPoints; TransitDir transitDir = TransitDirection(inputDirection, false); PlayAnim(transitDir); break; case ConnectionType.direct: desiredPosition = _targetPoint.transform.position; _targetState = ClimbState.onPoint; transitDir = TransitDirection(direction, false); Debug.Log(transitDir.ToString()); PlayAnim(transitDir); break; case ConnectionType.dismount: desiredPosition = _targetPoint.transform.position; _anim.SetInteger("JumpType", 20); _anim.SetBool("Move", true); break; } _targetPosition = desiredPosition; }
//=================================================================================================================o // Reached the top, PullUp void PullUp() { Vector3 topVec = lastHeroPos + hero.up * 2.3f; Vector3 fwdVec = topVec + hero.forward * 1.5f; // Step uo if (Vector3.Distance(hero.position, lastHeroPos) <= 2.1f) { hero.position = Vector3.Lerp(hero.position, topVec, Time.deltaTime * climbSpeed * 4.5f); } else // Step forward { hero.position = Vector3.Lerp(hero.position, fwdVec, Time.deltaTime * climbSpeed * 4); // Exit if (Vector3.Distance(topVec, hero.position) >= 0.7f) { climbState = ClimbState.None; } } isPullUp = false; }
private void Climb(ClimbState state) { if (state == ClimbState.climbUp) { climbAxis = 1; } if (state == ClimbState.wait) { climbAxis = 0; } if (state == ClimbState.climbDown) { climbAxis = -1; } anim.SetFloat("ClimbAxis", climbAxis * 2); rb.MovePosition(new Vector3(transform.position.x, transform.position.y + climbAxis * Time.deltaTime)); }
void BetweenPoints(Vector3 direction) { var n = _targetPoint.GetNeighbour(_prevPoint); if (n != null) { if (direction == n.direction) { _targetPoint = _prevPoint; Debug.Log("Moving to pervpoint?"); } else { Debug.Log("Doing nothing"); } } _targetPosition = _targetPoint.transform.position; _climbState = ClimbState.inTransit; _targetState = ClimbState.onPoint; _prevPoint = _curPoint; _lockInput = true; _anim.SetBool("Move", false); }
private void Detach(ClimbState climbState) { // Set player status playerState = climbState; if (climbState == ClimbState.DISMOUNTING) { // set start and end start = player.position; // have player dismount forward if climbing off top of ladder end = player.position + (-transform.forward * detachDistanceTop); } else { // Clear player values playerMotor.enabled = true; playerMotor = null; playerCtrl = null; } // Reset values to initial state isInTrigger = false; t_lerp = 0; }
//=================================================================================================================o void Climb() { Vector3 edgePos = nextPoint + ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); // Apply lift up hero.position = Vector3.Lerp(hero.position, edgePos, Time.deltaTime * climbSpeed * 8); // At edge if (Vector3.Distance(hero.position, edgePos) <= 0.1f) { if (isOverhang) { StartCoroutine(Overhang()); } else { if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; } } }
//=================================================================================================================o //==================================================Climb==========================================================o //=================================================================================================================o void _Climb() { // Current state info for layer Base animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); // Switch climb states switch (climbState) { case ClimbState.None: if (!reset) { ExitClimb(); } CheckClimb(); break; case ClimbState.Climb: ClimbTo(); reset = false; break; case ClimbState.Top: isTop = false; PullUp(); reset = false; break; case ClimbState.Wall: WallClimb(); reset = false; break; case ClimbState.Area: ClimbTo(); reset = false; break; case ClimbState.Edge: EdgeClimb(); reset = false; break; case ClimbState.Corner: CornerLerp(climbSpeed); reset = false; break; } if (doJumpDown) { if (v != 0) jumpOffNext = true; else jumpOffNext = false; climbState = ClimbState.None; } if (!animator.IsInTransition(0)) { // Resetting-------------------------------------------------- if (animatorStateInfo.IsTag("Jump")) { // Reset our parameter to avoid looping animator.SetBool("Jump", false); // RESET } if (animatorStateInfo.IsTag("Oh")) { animator.SetBool("Overhang", false); // RESET isOverhang = false; } } }
//=================================================================================================================o // Jump to next spot void WallJump() { if (hMove.Grounded) // Jump to wall { // if Grounded and edge is very close, just snap! And not wall and area climbing! if (Vector3.Distance ( hero.position, nextPoint ) <= 2.5f && (curT.name != "climbWall" && curT.name != "climbArea")) { Climb(); } else // do a walljump { hero.Translate( hero.up * Time.deltaTime * climbSpeed * 8 ); } } else // Air/Edge { if (curT.name == "climbArea") { // Jump to position Vector3 edgePos = nextPoint + ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); // Apply lift up hero.position = Vector3.Lerp (hero.position, edgePos, Time.deltaTime * climbSpeed * 8 ); // 10 // At position if (Vector3.Distance ( hero.position, edgePos ) <= 0.1f) { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallClimb; // Out } } else if (curT.name == "climbWall") { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallClimb; // Out } else Climb(); // Climb to --> Edge and Out } }
//=================================================================================================================o void Start() { hero = transform; //a = GetComponent <Animation>() as Animation; if (a.clip) { aC = a.clip; } else aC = a["idle"].clip; impactM = a["land"].clip; hMotor = GetComponent <HeroMotor>() as HeroMotor; hClimb = GetComponent <HeroClimb>() as HeroClimb; hPhys = GetComponent <HeroPhysic>() as HeroPhysic; hSwim = GetComponent <HeroSwim>() as HeroSwim; hKey = GetComponent <HeroKeymap>() as HeroKeymap; // Pass Delegates hMotor.doJumpDel += DoJump; hMotor.doBalanceDel += DoBalance; hMotor.doCombatDel += DoCombat; hMotor.doSwitchWeapDel += DoSwitchWeapons; hMotor.doEvadeDel += DoEvade; hMotor.doSneakDel += DoSneak; hClimb.doClimbDel += DoClimb; hSwim.doSwimDel += DoSwim; hPhys.doPhysDel += DoPhysx; currRot = 0.0f; leanRot = 0.0f; //sprintRot = 0.0f; lastRootForward = hero.forward; // Start is in Weaponstate.None, weaponless // Sword if (sword_Hand == null) // If no weapon is assigned { sword_Hand = new GameObject("emptyObj"); sword_Hand.active = false; } else sword_Hand.active = false; if (sword_Holster == null) // If no weapon is assigned { sword_Holster = new GameObject("emptyObj"); sword_Holster.active = false; } else sword_Holster.active = false; // Bow if (bow_Hand == null) // If no weapon is assigned { bow_Hand = new GameObject("emptyObj"); bow_Hand.active = false; } else bow_Hand.active = false; if (bow_Holster == null) // If no weapon is assigned { bow_Holster = new GameObject("emptyObj"); bow_Holster.active = false; } else bow_Holster.active = false; // Quiver if (bow_Quiver == null) // If no weapon is assigned { bow_Quiver = new GameObject("emptyObj"); bow_Quiver.active = false; } else bow_Quiver.active = false; // Rifle if (rifle_Hand == null) // If no weapon is assigned { rifle_Hand = new GameObject("emptyObj"); rifle_Hand.active = false; } else rifle_Hand.active = false; if (rifle_Holster == null)// If no weapon is assigned { rifle_Holster = new GameObject("emptyObj"); rifle_Holster.active = false; } else rifle_Holster.active = false; // Pistol if (pistol_Hand == null)// If no weapon is assigned { pistol_Hand = new GameObject("emptyObj"); pistol_Hand.active = false; } else pistol_Hand.active = false; if (pistol_Holster == null)// If no weapon is assigned { pistol_Holster = new GameObject("emptyObj"); pistol_Holster.active = false; } else pistol_Holster.active = false; // Look for setup DoSwitchWeapons (); actionState = ActionState.None; evadeState = EvadeState.None; climbState = ClimbState.None; }
//=================================================================================================================o // Moving sideways on edge void EdgeMovement() { Vector3 relPoint = curT.InverseTransformPoint(hero.position); SmoothToSpot(Mathf.Abs(relPoint.z), offsetToWall, Vector3.forward, Vector3.back); SmoothToSpot(Mathf.Abs(relPoint.y), heightOffsetToEdge, Vector3.up, Vector3.down); // Drop down if (Input.GetAxis("Vertical") < 0.0f /* || relPoint.z > 5f*/) { climbState = ClimbState.None; } // One handed on edge, animation trigger else if (Mathf.Abs(relPoint.x) >= 0.44f) { // Right side if (relPoint.x >= 0.44f) { if (doClimbDel != null) { doClimbDel("HangR"); } atHangR = true; // Hang at right end if (relPoint.x >= 0.5f) { climbState = ClimbState.None; // Out } } // Left side else if (relPoint.x <= -0.44f) { if (doClimbDel != null) { doClimbDel("HangL"); } atHangL = true; // Hang at left end if (relPoint.x <= -0.5f) { climbState = ClimbState.None; // Out } } } // Early out if (Input.GetAxis("Horizontal") == 0.0f) { return; } // Left / Right check for new spots else { Vector3 origin = hero.position - (hero.forward * -offsetToWall) - (hero.up * -heightOffsetToEdge); float xInpt = Input.GetAxis("Horizontal") > 0.0f ? 1.0f : -1.0f; Vector3 dir = Input.GetAxis("Horizontal") > 0.0f ? hero.right : -hero.right; cornerSideOffset = Input.GetAxis("Horizontal") > 0.0f ? -0.4f : 0.4f; RaycastHit hit; if (Physics.SphereCast(origin, 0.2f, dir, out hit, 0.3f, climbLayers)) { nextPoint = hit.point; lastT = curT; curT = hit.transform; inClimbRot = true; rot = hero.rotation; if (doClimbDel != null) { doClimbDel("Corner"); } climbState = ClimbState.Corner; // Out } // Speed interval if (!speedInterval) { StartCoroutine(SpeedInterval(0.2f, climbSpeed)); // 0.2f, climbspeed } // Apply hero.Translate(xInpt * Time.deltaTime * edgeSpeed, 0, 0, curT); // If not close to end if ((Mathf.Abs(relPoint.x) < 0.44f) && (atHangR || atHangL)) { if (doClimbDel != null) { doClimbDel("Edge"); } atHangR = false; atHangL = false; } } }
//=================================================================================================================o IEnumerator Overhang() { if (doClimbDel != null) { doClimbDel("Overhang"); } climbState = ClimbState.Overhang; yield return new WaitForSeconds (0.05f); if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; isOverhang = false; }
//=================================================================================================================o // At corner change climb handle void CornerLerp(float speed) { Vector3 tVec = nextPoint - (hero.right * -cornerReach) - (hero.forward * climbOffsetToWall) - (hero.up * heightOffsetToEdge); float angleTo = Vector3.Angle(hero.right, curT.transform.right); // Faster if angle is rel small speed = angleTo <= 15.0f ? speed *= 15 : speed *= 4; // Avoid hanging animator.SetBool("HangL", false); // RESET animator.SetBool("HangR", false); // RESET // Apply hero.position = Vector3.Lerp(hero.position, tVec, Time.deltaTime * speed); hero.rotation = Quaternion.Lerp(hero.rotation, curT.rotation, Time.deltaTime * speed); // Shift inward a bit if (angleTo <= 0.01f) { Vector3 relPoint = curT.InverseTransformPoint(hero.position); MatchP(Mathf.Abs(relPoint.z), climbOffsetToWall, Vector3.forward, Vector3.back); animator.SetBool("CornerL", false); // RESET animator.SetBool("CornerR", false); // RESET climbState = ClimbState.Edge; // Out } }
//=================================================================================================================o IEnumerator PreShort(ClimbState cS) { isPreShort = true; // Switch fast to next step if falling float seconds = climbState != ClimbState.None ? 0.75f : 0.0f; // Delegate to trigger animation state if (doClimbDel != null) { doClimbDel("PreShort"); } climbState = ClimbState.PreShort; // prepare for short distance climb (Animation) yield return new WaitForSeconds (seconds); if (Input.GetAxis("Vertical") > .5 && climbState == ClimbState.PreShort) // Climb up { if (doClimbDel != null) { doClimbDel("Short"); } climbState = cS; //ClimbState.Climb; // Move to edge } else // Stay at position { isPullUp = false; isOverhang = false; yield return new WaitForSeconds (0.3f); // Fade to hang pose if ( curT != null && curT.name != "climbArea") { nextPoint = hero.position - ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); //lastPoint; curT = lastT; climbState = ClimbState.Climb; // To last } else // We hit a Wall collider start climbing { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallClimb; } } isPreShort = false; }
//=================================================================================================================o IEnumerator Prepare() { isPreparing = true; if (doClimbDel != null) { doClimbDel("Prepare"); } climbState = ClimbState.Prepare; yield return new WaitForSeconds (0.9f); if (Input.GetAxis("Vertical") > .5 && climbState == ClimbState.Prepare) // Climb up { if (doClimbDel != null) { doClimbDel("Climb"); } climbState = ClimbState.Climb; // Move to edge } else // Stay at position { isPullUp = false; isOverhang = false; yield return new WaitForSeconds (0.2f); // Fade to hang pose nextPoint = hero.position - ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); //Current position curT = lastT; climbState = ClimbState.Climb; // To last position } isPreparing = false; }
//=================================================================================================================o IEnumerator PreTop() { isPreparing = true; if (curT.name == "climbObjectTopOh") { if (doClimbDel != null) { doClimbDel("PreOh"); } // Overhang } else { if (doClimbDel != null) { doClimbDel("Prepare"); } // Normal } climbState = ClimbState.Prepare; yield return new WaitForSeconds (0.2f);//transition to top if (Input.GetAxis("Vertical") > .5 && climbState == ClimbState.Prepare) // Climb up { if (doClimbDel != null) { doClimbDel("Top"); } climbState = ClimbState.Top; // Out } else // Stay at position { yield return new WaitForSeconds (0.2f); // Fade to hang pose if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; } isPreparing = false; }
//=================================================================================================================o // Reached the top, PullUp void PullUp() { Vector3 topVec = lastHeroPos + hero.up * 2.3f; Vector3 fwdVec = topVec + hero.forward * 1.5f; // Step uo if (Vector3.Distance (hero.position, lastHeroPos) <= 2.1f) { hero.position = Vector3.Lerp (hero.position, topVec, Time.deltaTime * climbSpeed *4.5f); } else // Step forward { hero.position = Vector3.Lerp (hero.position, fwdVec, Time.deltaTime * climbSpeed *4); // Exit if (Vector3.Distance (topVec, hero.position) >= 0.7f) { climbState = ClimbState.None; } } isPullUp = false; }
//=================================================================================================================o void Start() { hero = transform; rb = rigidbody; climbState = ClimbState.None; Physics.IgnoreLayerCollision(8,9); // ignore player / climb collision hMove = GetComponent <HeroMotor> () as HeroMotor; hSwim = GetComponent <HeroSwim> () as HeroSwim; hKey = GetComponent <HeroKeymap> () as HeroKeymap; cacheDist = checkDistance; }
//=================================================================================================================o // Look for objects to climb void CheckClimb() { if (!canClimb) return; if (doClimb && v > 0.2) // Up { // Reduce check distance/height while falling if (!grounded && baseState == BaseState.Base) { climbCheckDistance = 0.4f; } else climbCheckDistance = cacheDist; Vector3 p1 = hero.position - (hero.up * -heightOffsetToEdge) + hero.forward; Vector3 p2 = hero.position - (hero.up * -heightOffsetToEdge) - hero.forward; RaycastHit hit; // Hit nothing and not at edge -> Out if (!Physics.CapsuleCast(p1, p2, climbCheckRadius, hero.up, out hit, climbCheckDistance, climbLayers)) return; // If not almost facing the edge cancel/Out if (Vector3.Angle(hero.right, hit.transform.right) >= 60.0f) return; if (isTop) return; if (curT != hit.transform) { curT = hit.transform; nextPoint = hit.point; } hero.rotation = Quaternion.Euler(curT.eulerAngles.x, curT.eulerAngles.y, 0); animator.SetInteger("RandomM", Random.Range(0, 3)); if (curT.name == "climbObject") { rigidbody.isKinematic = true; climbState = ClimbState.Climb; } else if (curT.name == "climbObjectOh") { rigidbody.isKinematic = true; isOverhang = true; climbState = ClimbState.Climb; } else if (curT.name == "climbObjectTop") { rigidbody.isKinematic = true; isTop = true; climbState = ClimbState.Climb; } else if (curT.name == "climbObjectTopOh") { rigidbody.isKinematic = true; isTop = true; isOverhang = true; climbState = ClimbState.Climb; } else if (curT.name == "climbWall") { rigidbody.isKinematic = true; isTop = true; if (grounded) climbState = ClimbState.Wall; else climbState = ClimbState.Area; } else if (curT.name == "climbArea") { rigidbody.isKinematic = true; climbState = ClimbState.Area; } else { climbState = ClimbState.None; } isClimb = true; // UP climbUp = true; // Long or Short ? climbLong = hit.distance > 1 ? true : false; } else if (doClimb && v < -0.2) // Down { // Reduce check distance/height while falling if (!grounded && baseState == BaseState.Base) { climbCheckDistance = 0.4f; } else climbCheckDistance = cacheDist; Vector3 p1 = hero.position - (hero.up * -heightOffsetToEdge) + hero.forward; Vector3 p2 = hero.position - (hero.up * -heightOffsetToEdge) - hero.forward; RaycastHit hit; // Hit nothing and not at edge -> Out if (!Physics.CapsuleCast(p1, p2, climbCheckRadius, -hero.up, out hit, climbCheckDistance, climbLayers)) return; // If not almost facing the edge cancel/Out if (Vector3.Angle(hero.right, hit.transform.right) >= 60.0f) return; if (curT != hit.transform) { curT = hit.transform; nextPoint = hit.point; } hero.rotation = Quaternion.Euler(0, curT.eulerAngles.y, 0); isTop = false; // RESET animator.SetBool("Top", false); // RESET animator.SetInteger("RandomM", Random.Range(0, 3)); if (curT.name == "climbObject") { rigidbody.isKinematic = true; climbState = ClimbState.Climb; } else if (curT.name == "climbObjectOh") { rigidbody.isKinematic = true; isOverhang = true; climbState = ClimbState.Climb; } else if (curT.name == "climbObjectTop") { rigidbody.isKinematic = true; isTop = true; climbState = ClimbState.Climb; } else if (curT.name == "climbObjectTopOh") { rigidbody.isKinematic = true; isTop = true; isOverhang = true; climbState = ClimbState.Climb; } else if (curT.name == "climbWall") { climbState = ClimbState.None; } else if (curT.name == "climbArea") { rigidbody.isKinematic = true; climbState = ClimbState.Area; } else { climbState = ClimbState.None; } isClimb = true; // Down climbUp = false; // Long or Short ? climbLong = hit.distance > 1 ? true : false; //print ("Down"); } }
//=================================================================================================================o void ExitClimb() { // Base State if (animCtrl.climb) { rigidbody.isKinematic = false; isTop = false; // RESET isOverhang = false; // RESET hero.rotation = Quaternion.Euler(0, curT.eulerAngles.y, 0); curT = null; climbState = ClimbState.None; animator.runtimeAnimatorController = animCtrl.baseC; baseState = BaseState.Base; reset = true; // Out } }
//=================================================================================================================o void ClimbTo() { // When entering Climb state if (isClimb) { if (climbUp) { if (climbLong) animator.SetBool("Climb", true); else animator.SetBool("ClimbShort", true); isClimb = false; } else { if (climbLong) animator.SetBool("ClimbDown", true); else animator.SetBool("ClimbDownShort", true); isClimb = false; } } if (grounded && v < 0) // On ground and going down { climbState = ClimbState.None; } if (!animatorStateInfo.IsTag("Pre")) { Vector3 edgePos = nextPoint + ((hero.up * -heightOffsetToEdge) - (hero.forward * climbOffsetToWall)); // Apply lift up hero.position = Vector3.Lerp(hero.position, edgePos, Time.deltaTime * climbSpeed * 11); if (Vector3.Distance(hero.position, edgePos) <= 0.1f) { animator.SetBool("Climb", false); // RESET animator.SetBool("ClimbShort", false); // RESET animator.SetBool("ClimbDown", false); // RESET animator.SetBool("ClimbDownShort", false); // RESET if (isOverhang) animator.SetBool("Overhang", true); if (curT.name == "climbArea" || curT.name == "climbWall") { climbState = ClimbState.Wall; // Out } else climbState = ClimbState.Edge; // Out } } }
//=================================================================================================================o // At corner change climb handle void CornerLerp(float speed) { Vector3 v = nextPoint - (hero.right * cornerSideOffset) - (hero.forward * offsetToWall) - (hero.up * heightOffsetToEdge); float angleTo = Vector3.Angle (hero.right, curT.transform.right); // Faster if angle is rel small speed = angleTo <= 15.0f ? speed *= 15 : speed *= 4; // Apply hero.position = Vector3.Lerp (hero.position, v, Time.deltaTime * speed); hero.rotation = Quaternion.Lerp (hero.rotation, curT.rotation, Time.deltaTime * speed); // Shift inward a bit if (angleTo <= 0.01f) { Vector3 relPoint = curT.InverseTransformPoint (hero.position); SmoothToSpot (Mathf.Abs(relPoint.z), offsetToWall, Vector3.forward, Vector3.back); if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; // Out } // Reset hang atHangR = false; atHangL = false; }
//=================================================================================================================o void EdgeClimb() { Vector3 relPoint = curT.InverseTransformPoint(hero.position); MatchP(Mathf.Abs(relPoint.z), climbOffsetToWall, Vector3.forward, Vector3.back); MatchP(Mathf.Abs(relPoint.y), heightOffsetToEdge, Vector3.up, Vector3.down); if (isOverhang) { animator.SetBool("Overhang", true); } if (!animatorStateInfo.IsTag("Oh") && !animator.IsInTransition(0)) // not if overhanging { // Horizontal climbing if (h != 0.0f) { Vector3 origin = hero.position - (hero.forward * -climbOffsetToWall) - (hero.up * -heightOffsetToEdge); if (h > 0.0f) // Check right { RaycastHit hit; if (Physics.SphereCast(origin, 0.2f, hero.right, out hit, 0.4f, climbLayers)) { nextPoint = hit.point; curT = hit.transform; animator.SetBool("CornerR", true); cornerReach = 0.4f; climbState = ClimbState.Corner; // Out } // Edge speed interval, min - max speed. float edgeSpeed = animatorStateInfo.normalizedTime % 1 < 0.5f ? 0.9f : 0.3f; // Apply hero.Translate(1 * Time.deltaTime * edgeSpeed, 0, 0, curT); } else // Check left { RaycastHit hit; if (Physics.SphereCast(origin, 0.2f, -hero.right, out hit, 0.4f, climbLayers)) { nextPoint = hit.point; curT = hit.transform; animator.SetBool("CornerL", true); cornerReach = -0.4f; climbState = ClimbState.Corner; // Out } // Edge speed interval, min - max speed. float edgeSpeed = animatorStateInfo.normalizedTime % 1 < 0.5f ? 0.3f : 0.9f; // Apply hero.Translate(-1 * Time.deltaTime * edgeSpeed, 0, 0, curT); } } // Top if (isTop && doClimb) { animator.SetBool("Top", true); climbState = ClimbState.Top; // Out } } // Right End if (relPoint.x >= 0.44f) { animator.SetBool("HangR", true); if (relPoint.x >= 0.5f) climbState = ClimbState.None; // Out } // Left End else if (relPoint.x <= -0.44f) { animator.SetBool("HangL", true); if (relPoint.x <= -0.5f) climbState = ClimbState.None; // Out } else { animator.SetBool("HangL", false); // RESET animator.SetBool("HangR", false); // RESET // While not hanging, preparing or climbing if ((!animatorStateInfo.IsTag("Pre") || !animatorStateInfo.IsTag("Climb")) && !animator.IsInTransition(0)) CheckClimb(); // Find next } }
//=================================================================================================================o // Reset if leaving Climb modus public void ExitClimb() { rb.isKinematic = false; hMove.canMove = true; atHangR = false; atHangL = false; isWall = false; isPullUp = false; curT = null; lastT = null; rb.AddForce( Vector3.down * 2, ForceMode.VelocityChange); // Restore Rotation if (inClimbRot) { hero.rotation = Quaternion.Euler (0, rot.eulerAngles.y, 0); inClimbRot = false; } isClimbing = false; if (doClimbDel != null) { doClimbDel("None"); } climbState = ClimbState.None; // Out reset = true; }
//=================================================================================================================o // Moving sideways on edge void EdgeMovement() { Vector3 relPoint = curT.InverseTransformPoint (hero.position); SmoothToSpot (Mathf.Abs(relPoint.z), offsetToWall, Vector3.forward, Vector3.back); SmoothToSpot (Mathf.Abs(relPoint.y), heightOffsetToEdge, Vector3.up, Vector3.down); // Drop down if (Input.GetAxis("Vertical") < -0.5f/* || relPoint.z > 5f*/) { climbState = ClimbState.None; } // One handed on edge, animation trigger else if (Mathf.Abs(relPoint.x) >= 0.44f) { // Right side if (relPoint.x >= 0.44f) { if (doClimbDel != null) { doClimbDel("HangR"); } atHangR = true; // Hang at right end if (relPoint.x >= 0.5f) { climbState = ClimbState.None; // Out } } // Left side else if (relPoint.x <= -0.44f) { if (doClimbDel != null) { doClimbDel("HangL"); } atHangL = true; // Hang at left end if (relPoint.x <= -0.5f) { climbState = ClimbState.None; // Out } } } // Early out if (Input.GetAxis ("Horizontal") == 0.0f) return; // Left / Right check for new spots else { Vector3 origin = hero.position - (hero.forward * -offsetToWall) - (hero.up * -heightOffsetToEdge); float xInpt = Input.GetAxis ("Horizontal") > 0.0f ? 1.0f : -1.0f; Vector3 dir = Input.GetAxis ("Horizontal") > 0.0f ? hero.right : -hero.right; cornerSideOffset = Input.GetAxis ("Horizontal") > 0.0f ? -0.4f : 0.4f; RaycastHit hit; if (Physics.SphereCast (origin, 0.2f, dir, out hit, 0.3f, climbLayers)) { nextPoint = hit.point; lastT = curT; curT = hit.transform; inClimbRot = true; rot = hero.rotation; if (doClimbDel != null) { doClimbDel("Corner"); } climbState = ClimbState.Corner; // Out } // Speed interval if (!speedInterval) { StartCoroutine( SpeedInterval( 0.0f, climbSpeed)); // 0.2f, climbspeed } // Apply hero.Translate( xInpt * Time.deltaTime * edgeSpeed, 0, 0, curT ); // If not close to end if ((Mathf.Abs(relPoint.x) < 0.44f) && (atHangR || atHangL)) { if (doClimbDel != null) { doClimbDel("Edge"); } atHangR = false; atHangL = false; } } }
//=================================================================================================================o // Check for ledge collider in front void CheckLedge() { if (hMove.Grounded) { RaycastHit hit; if (!Physics.Raycast (hero.position + hero.up, hero.forward, 1f, climbLayers)) return; else if (Physics.Raycast (hero.position + hero.up, hero.forward, out hit, 1f, climbLayers)) { if (hit.collider.name == "climbLedge") { isClimbing = true; rb.isKinematic = true; hMove.canMove = false; isLedgeEnd = false; curT = hit.transform; lastHeroPos = hero.position; if (doClimbDel != null) { doClimbDel("Ledge"); } climbState = ClimbState.LedgeJump; } } } }
static void Everything() { // creates a variable for the time(seconds) float time = stopwatch.Duration; // prevents unexpected behavior rightDriveTalon.ConfigFactoryDefault(); leftDriveTalon.ConfigFactoryDefault(); climbTalon.ConfigFactoryDefault(); // not finished autonomous period if (time < 30) { Debug.Print("Auton is attempting to E"); leftDriveTalon.Set(ControlMode.PercentOutput, 0.5); //sets left drive talon to 50% rightDriveTalon.Set(ControlMode.PercentOutput, 0.5); //sets right drive talon to 50% Thread.Sleep(10); Debug.Print("Auton ending, E complete."); leftDriveTalon.Set(ControlMode.PercentOutput, 0.0); //sets left drive talon to 0% rightDriveTalon.Set(ControlMode.PercentOutput, 0.0); //sets right drive talon to 0% } while (running) { // print axis value ??? Debug.Print("axis:" + gamepad1.GetAxis(1)); // allows motor control CTRE.Phoenix.Watchdog.Feed(); // Teleoperated // determine inputs forwardAxis = gamepad1.GetAxis(1); turnAxis = gamepad1.GetAxis(2); // accounting for forward and turn b4 Eing into the talons finalLeftTalonValue = (forwardAxis * forwardGain) + (turnAxis * turnGain); finalRightTalonValue = (forwardAxis * forwardGain) - (turnAxis * turnGain); // pass motor value to Talons leftDriveTalon.Set(ControlMode.PercentOutput, finalLeftTalonValue); rightDriveTalon.Set(ControlMode.PercentOutput, finalRightTalonValue); // Elevator controls if (gamepad1.GetButton(elevatorRise)) { climbState = ClimbState.RISE; } else if (gamepad1.GetButton(elevatorLower)) { climbState = ClimbState.LOWER; } else { climbState = ClimbState.IDLE; } // if the button is pressed the drivestate will switch if (gamepad1.GetButton(driveStateButton) && driveState == DriveState.PRECISE) { driveState = DriveState.STRONGER; } else if (gamepad1.GetButton(driveStateButton) && driveState == DriveState.STRONGER) { driveState = DriveState.PRECISE; } // elevator state machine switch (climbState) { case ClimbState.IDLE: Debug.Print("nothing"); climbTalon.Set(ControlMode.PercentOutput, 0.0); //sets the climber talon to 0% break; case ClimbState.RISE: Debug.Print("rising"); climbTalon.Set(ControlMode.PercentOutput, 1 * climbGain); //sets the climber talon to 50% break; case ClimbState.LOWER: Debug.Print("lowering"); climbTalon.Set(ControlMode.PercentOutput, -1 * climbGain); //sets the climber talon to -50% break; case ClimbState.ERROR: Debug.Print("ElevatorState error"); break; default: Debug.Print("very bad error"); break; } // drive gain state machine switch (driveState) { case DriveState.PRECISE: forwardGain = 0.3f; turnGain = 0.1f; Debug.Print("precise"); break; case DriveState.STRONGER: forwardGain = 0.5f; turnGain = 0.25f; Debug.Print("stronger"); break; default: Debug.Print("DriveState error"); break; } if (gamepad1.GetButton(emergencyStop)) { running = false; } } }
//=================================================================================================================o // Wall climb handling void WallClimb() { Vector3 relV = curT.InverseTransformPoint(hero.position); float distY = Mathf.Abs(relV.y); float distZ = Mathf.Abs(relV.z); // Limit is almost the edge if (distY >= heightOffsetToEdge * 1.1f) { SmoothToSpot (distZ, offsetToWall, Vector3.forward, Vector3.back); // Input if (Input.GetAxis ("Vertical") != 0.0f) { if (Input.GetAxis ("Vertical") > 0.0f) { inputVec = hero.TransformPoint( Vector3.up ); } else { inputVec = hero.TransformPoint( Vector3.down ); if (!Physics.Raycast(hero.position, hero.forward, offsetToWall, climbLayers) || hMove.Grounded) { climbState = ClimbState.None; } } // Apply movement hero.position = Vector3.Lerp( hero.position, inputVec, Time.deltaTime * climbSpeed * 1.3f); } else // Stop if there's no input { inputVec = hero.TransformPoint( Vector3.zero ); } } else // Reached the edge { if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; // Out } // Drop // Action key down to Exit if (Input.GetKeyDown (hKey.jumpKey) && !hMove.Grounded) { climbState = ClimbState.None; // Out } }
//=================================================================================================================o void Climb() { Vector3 edgePos = nextPoint + ((hero.up * -heightOffsetToEdge) - (hero.forward * offsetToWall)); // Apply lift up hero.position = Vector3.Lerp (hero.position, edgePos, Time.deltaTime * climbSpeed * 8 ); // At edge if (Vector3.Distance ( hero.position, edgePos ) <= 0.1f) { if (isOverhang) { StartCoroutine( Overhang()); } else { if (doClimbDel != null) { doClimbDel("Edge"); } climbState = ClimbState.Edge; } } }
void WallClimb() { Vector3 way = rigid.velocity; if (isGrounded) { wallClimb = ClimbState.None; } switch (wallClimb) { case ClimbState.Jumping: case ClimbState.None: if (way.y >= 0.0f || isGrounded || (wallClimb == ClimbState.Jumping && Mathf.Abs(transform.eulerAngles.y - LastWallAngle) < 100f)) { return; } way.y = 0.0f; way.Normalize(); bool foundWall = false; bool firstWall = false; // Did the raycast find a wall? (if not then climb to top) for (int i = 0; i < wallOffsets.Length && !foundWall; i++) { Vector3 pos = transform.forward * wallOffsets[i].z; pos.y = wallOffsets[i].y; pos += transform.position; foundWall = foundWall || Physics.Raycast(pos, transform.forward, wallDistance, wallLayers.value); if (i == 0) { firstWall = foundWall; } Debug.DrawRay(pos, transform.forward * wallDistance, Color.green, 1.0f); } if (!foundWall) { return; } if (!firstWall) { // Jump up } wallClimb = ClimbState.Climbing; climbStartY = transform.position.y; LastWallAngle = transform.eulerAngles.y; break; case ClimbState.Climbing: rigid.velocity = Vector3.up * ClimbSpeed * Time.deltaTime; if (Mathf.Abs(transform.position.y - climbStartY) > ClimbDistance) { wallClimb = ClimbState.Sliding; } break; case ClimbState.Sliding: if (isGrounded) { wallClimb = ClimbState.None; } if (Input.GetButtonDown("Jump")) { WallJump(); return; } rigid.velocity = Vector3.down * wallSlideSpeed * Time.deltaTime; break; default: break; } }
//=================================================================================================================o // Find next spot and climb up void Check() { // Action button E to start climbing if (Input.GetAxis("Vertical") > .5 && (climbState == ClimbState.None || climbState == ClimbState.Edge) && hMove.isAfterTap)//Input.GetKey(hKey.climbOrStandKey) { Vector3 p1 = hero.position - (hero.up * -heightOffsetToEdge) + hero.forward; Vector3 p2 = hero.position - (hero.up * -heightOffsetToEdge) - hero.forward; RaycastHit hit; CheckLedge (); // Reduce check distance/height while falling if (!hMove.Grounded && climbState == ClimbState.None && !hSwim.isSwimming) { checkDistance = 0.4f; } else checkDistance = cacheDist; // Hit nothing and not at edge -> Out if (!Physics.CapsuleCast (p1, p2, checkRadius, hero.up, out hit, checkDistance, climbLayers) && (climbState != ClimbState.Edge)) return; // Get next edge point location else if (Physics.CapsuleCast (p1, p2, checkRadius, hero.up, out hit, checkDistance, climbLayers) && !isPullUp) { if ((hit.collider.name == "climbObject" || hit.collider.name == "climbObjectTop" || hit.collider.name == "climbObjectTopOh" || hit.collider.name == "climbObjectOh") && hit.transform != curT) { // If not almost facing the edge cancel/Out if (Vector3.Angle (hero.right, hit.transform.right) >= 60.0f) return; isClimbing = true; rb.isKinematic = true; hMove.canMove = false; nextPoint = hit.point; lastT = curT; curT = hit.transform; // Hero rotation hero.rotation = hit.transform.rotation; inClimbRot = true; rot = hero.rotation; // Jump to edge if grounded or start climbing if (hMove.Grounded) { if (doClimbDel != null) { doClimbDel("WallJump"); } climbState = ClimbState.WallJump; if ((hit.collider.name == "climbObjectTopOh") || (hit.collider.name == "climbObjectTop")) { isPullUp = true; if ((hit.collider.name == "climbObjectTopOh")) isOverhang = true; } else if ((hit.collider.name == "climbObjectOh")) { isOverhang = true; } } else // Not grounded { // Standard climb if (climbState == ClimbState.Edge) // Prepare & climb up { if (hit.distance > 1) // Distance is bigger than { if (!isPreparing) // if coroutine has finished { StartCoroutine( Prepare()); } if (hit.collider.name == "climbObjectOh") isOverhang = true; } else // Short climb action { if (!isPreShort) // if coroutine has finished { StartCoroutine( PreShort( ClimbState.Climb )); } } if ((hit.collider.name == "climbObjectTop") || (hit.collider.name == "climbObjectTopOh")) { isPullUp = true; if (hit.collider.name == "climbObjectTopOh") isOverhang = true; } } else if (climbState == ClimbState.None) // Falling { if (doClimbDel != null) { doClimbDel("Catch"); } // Trigger catch motion climbState = ClimbState.Climb; // move to edge we hit if ((hit.collider.name == "climbObjectTop") || (hit.collider.name == "climbObjectTopOh")) { isPullUp = true; if (hit.collider.name == "climbObjectTopOh") isOverhang = true; } } } } // Hit a climb wall collider else if (hit.collider.name == "climbWall" || hit.collider.name == "climbArea" && climbState != ClimbState.WallClimb && climbState != ClimbState.WallJump) { // If not almost facing the wall cancel/Out if (Vector3.Angle (hero.right, hit.transform.right) >= 60.0f) return; isClimbing = true; rb.isKinematic = true; hMove.canMove = false; nextPoint = hit.point; lastT = curT; curT = hit.transform; // Hero rotation hero.rotation = hit.transform.rotation; inClimbRot = true; rot = hero.rotation; // Wall-climb-jump modus if (curT.name == "climbWall") { isWall = true; if (hMove.Grounded || hSwim.isSwimming) { if (doClimbDel != null) { doClimbDel("WallJump"); } climbState = ClimbState.WallJump; } else { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallClimb; } } else // Wall-climb area { /*if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallJump;*/ if (!isPreShort && !hMove.Grounded) // if coroutine has finished { StartCoroutine( PreShort( ClimbState.WallJump )); } else // Grounded { if (doClimbDel != null) { doClimbDel("WallClimb"); } climbState = ClimbState.WallJump; } } } } // End, climb on top else if (isPullUp || isWall) { isClimbing = true; lastHeroPos = hero.position; if (!isPreparing) // if coroutine has finished , PullUp() { StartCoroutine( PreTop()); } } } }
//=================================================================================================================o // Jump over ledge void LedgeJump() { Vector3 topVec = new Vector3 (lastHeroPos.x, curT.position.y + 0.3f, lastHeroPos.z); Vector3 fwdVec = topVec + hero.forward * 2.0f; Vector3 dwnVec = hero.position - (hero.up * 3f); // Up if (((hero.position.y - curT.position.y) <= 0.0f) && !isLedgeEnd) { hero.position = Vector3.Lerp (hero.position, topVec, Time.deltaTime * climbSpeed * 5f); } else { // Forward if (!isLedgeEnd) { hero.position = Vector3.Lerp (hero.position, fwdVec, Time.deltaTime * climbSpeed * 9f); } // Down & Exit if (Vector3.Distance(topVec, hero.position) >= 1.8f) // Forward distance to go over the ledge { isLedgeEnd = true; hero.position = Vector3.Lerp (hero.position, dwnVec, Time.deltaTime * climbSpeed * 1.0f); if (hMove.Grounded) { climbState = ClimbState.None; } } } }
void Update() { if (playerState == ClimbState.NONE) { if (isInTrigger) { if (Input.GetAxis(TAG_AXIS_V) > 0) // Player moving forward { // Attach player to ladder playerMotor.grounded = false; // (prevent jump if dropping off ladder) playerMotor.enabled = false; // disable normal movement playerState = ClimbState.CENTERING; // center player with ladder } } } else if (playerState == ClimbState.CENTERING) { if (t_lerp == 0) { // initialize values start = player.position; end = new Vector3(transform.position.x, player.position.y, transform.position.z); } if (t_lerp < 1) { // center player t_lerp += Time.deltaTime / attachTime; player.position = Vector3.Lerp(start, end, t_lerp); } else { // finish centering t_lerp = 0; playerState = ClimbState.CLIMBING; } } else if (playerState == ClimbState.CLIMBING) { CollisionFlags playerCol = CollisionFlags.None; if (Input.GetKey(KeyCode.W)) // Player climbing up { playerCol = playerCtrl.Move(new Vector3(0, Time.deltaTime * climbSpeed, 0)); } else if (Input.GetKey(KeyCode.S)) // Player climbing down { playerCol = playerCtrl.Move(new Vector3(0, Time.deltaTime * -climbSpeed, 0)); } if (Input.GetKeyDown(KeyCode.Space)) // Player "let go" of ladder { Detach(ClimbState.NONE); } if ((playerCol & CollisionFlags.CollidedBelow) != 0) // player touched ground - release { Detach(ClimbState.NONE); } } else if (playerState == ClimbState.DISMOUNTING) { if (t_lerp < 1) { // Move player off ladder t_lerp += Time.deltaTime / detachTime; Vector3 diff = Vector3.Lerp(start, end, t_lerp) - player.position; playerCtrl.Move(diff); } else { // Enable player movement t_lerp = 0; Detach(ClimbState.NONE); } } }
//=================================================================================================================o // Reached the top, PullUp void PullUp() { if (animatorStateInfo.IsTag("Top") && !animator.IsInTransition(0)) { float nT = animatorStateInfo.normalizedTime; if (nT <= 1.0f) { if (nT <= 0.4f) // Step up { hero.Translate(Vector3.up * Time.deltaTime * climbSpeed * 8.0f); } else // Step forward { if (nT <= 0.6f) hero.Translate(Vector3.forward * Time.deltaTime * climbSpeed * 2.5f); else if (nT >= 0.6f && rigidbody.isKinematic) // fall early rigidbody.isKinematic = false; if (!rigidbody.isKinematic) rigidbody.velocity = new Vector3(0, rigidbody.velocity.y, 0); } } else // Animation is finished climbState = ClimbState.None; // Out } }
//=================================================================================================================o void DoClimb(string s) { if (s == "None") { climbState = ClimbState.None; isShort = false; } // Shortclimb reset else if (s == "WallClimb") { climbState = ClimbState.WallClimb; } else if (s == "WallJump") { climbState = ClimbState.WallJump; } else if (s == "PreOh") { climbState = ClimbState.PreOh; } else if (s == "Overhang") { climbState = ClimbState.Overhang; isShort = false; } else if (s == "Prepare") { climbState = ClimbState.Prepare; } else if (s == "PreShort") { climbState = ClimbState.PreShort; } else if (s == "Ledge") { climbState = ClimbState.Ledge; } else if (s == "Catch") { climbState = ClimbState.Catch; } else if (s == "Corner") { climbState = ClimbState.Corner; } else if (s == "HangL") { climbState = ClimbState.HangL; } else if (s == "HangR") { climbState = ClimbState.HangR; } else if (s == "Climb") { climbState = ClimbState.Climb; isShort = false; } else if (s == "Short") { climbState = ClimbState.Short; isShort = true; } else if (s == "Edge") { climbState = ClimbState.Edge; climbMotion = false; } // XFadeRandom() is ready now else if (s == "Top") { climbState = ClimbState.Top; } mainState = MainState.Climbing; }
//=================================================================================================================o void WallClimb() { if (grounded && v < 0) // On ground and going down { climbState = ClimbState.None; } Vector3 relV = curT.InverseTransformPoint(hero.position); Vector3 inputVec = hero.position; float distY = Mathf.Abs(relV.y); float distZ = Mathf.Abs(relV.z); animator.SetBool("WallClimb", true); // Limit is almost the edge if (distY >= heightOffsetToEdge * 1.1f) { MatchP(distZ, climbOffsetToWall, Vector3.forward, Vector3.back); // Input if (v != 0.0f) { if (v > 0.0f) { inputVec = hero.TransformPoint(Vector3.up); } else { inputVec = hero.TransformPoint(Vector3.down); if (!Physics.Raycast(hero.position, hero.forward, climbOffsetToWall, climbLayers) || grounded) { climbState = ClimbState.None; } } // Apply movement hero.position = Vector3.Lerp(hero.position, inputVec, Time.deltaTime * climbSpeed * 1.3f); } else // Stop if there's no input { inputVec = hero.TransformPoint(Vector3.zero); } } else // Reached the edge { animator.SetBool("WallClimb", false); // RESET climbState = ClimbState.Edge; // Out } }