/// <summary> /// 下にあるMapCollisionレイヤーのオブジェクトを返します。 /// </summary> /// <returns>見つけたオブジェクト。オブジェクトがなければnull</returns> public static int GetUnderMap() { Vector3 origin = ChrController.bounds.center; return(PhysicsCaster.Raycast( origin, Vector3.down, ChrController.height * 0.5f + 0.1f, PhysicsCaster.MapCollisionPlayerOnlyLayer)); }
/// <summary> /// 苗を置く候補座標を返します。 /// </summary> /// <param name="stellaPosition">ステラの座標</param> /// <returns>求めた苗の座標</returns> Vector3 GetPutPosition(Vector3 stellaPosition) { Vector3 naepos = stellaPosition; float absOffset = StellaMove.ActionBoxInstance.colliderCenter.x + StellaMove.ActionBoxInstance.halfExtents.x + StellaMove.naeActable.ColliderExtentsX; float baseX = naepos.x + absOffset * StellaMove.forwardVector.x; // 単位変換 naepos.x = Mathf.Round(baseX / naeUnit) * naeUnit; if (absOffset < (Mathf.Abs(naepos.x - stellaPosition.x))) { // 遠くなっているので、1単位近づける naepos.x -= naeUnit * StellaMove.forwardVector.x; } // 床の位置を調べる naepos.y = StellaMove.chrController.bounds.center.y; int grobj = PhysicsCaster.GetGround(naepos, float.PositiveInfinity); if (grobj == -1) { // 置けない高さを設定 naepos.y = (StellaMove.chrController.bounds.min.y - naePutUnderHeight * 2f); return(naepos); } naepos.y = PhysicsCaster.hits[grobj].collider.bounds.max.y; return(naepos); }
/// <summary> /// 上下キーが押されていて、ツタと重なっていたら、そのツタのインスタンスを返します。 /// </summary> /// <returns></returns> public static bool CheckIvyHold() { float v = Input.GetAxisRaw("Vertical"); // 上下キーが押されていなければなし if (Mathf.Approximately(v, 0f)) { return(false); } if (v < -0.5f) { // 下キーの時は、着地していたら移行無し Vector3 foot = ChrController.bounds.center; foot.y = ChrController.bounds.min.y; int goidx = PhysicsCaster.GetPlayerGround(foot, 0.1f); if (goidx != -1) { return(false); } } IvyInstance = CheckIvyOverlap(); if (IvyInstance == null) { return(false); } if (IsIvyUp()) { return(IvyInstance.Hold()); } return(false); }
void FixedUpdate() { #if UNITY_EDITOR if (!isDebugMovable) { #endif if (!StageManager.CanMove) { return; } #if UNITY_EDITOR } #endif stellaActionScriptableObjects[(int)NowAction]?.UpdateAction(); if (ChrController.collisionFlags.HasFlag(CollisionFlags.Below)) { // 下判定があったら、埋まっていないか確認 int cnt = PhysicsCaster.CharacterControllerCast(ChrController, Vector3.down, 0f, PhysicsCaster.MapCollisionLayer); float checkY = ChrController.bounds.min.y + walkDownY; for (int i = 0; i < cnt; i++) { ColliderIgnore[] ci = PhysicsCaster.hits[i].collider.GetComponents <ColliderIgnore>(); // 足元より上なら無効化 for (int j = 0; j < ci.Length; j++) { if (ci[j].Top > checkY) { ci[j].Sleep(); } } } } }
/// <summary> /// 乗っていた岩が下にあるかを確認します。 /// </summary> /// <returns>岩がある時、trueを返します。</returns> bool CheckGetOff() { Vector3 origin = StellaMove.ChrController.bounds.center; origin.x += getOffDistance * Mathf.Sign(lastRockObject.transform.position.x - origin.x); int hitCount = PhysicsCaster.Raycast(origin, Vector3.down, float.PositiveInfinity, PhysicsCaster.MapCollisionLayer, QueryTriggerInteraction.Collide); Collider res = FindRock(hitCount); if (res.gameObject == lastRockObject) { return(true); } // 列挙が越えていたら、一番上までで再列挙 while (hitCount >= PhysicsCaster.hits.Length) { hitCount = PhysicsCaster.Raycast(origin, Vector3.down, origin.y - res.bounds.max.y, PhysicsCaster.MapCollisionLayer, QueryTriggerInteraction.Collide); res = FindRock(hitCount); if (res.gameObject == lastRockObject) { return(true); } } GetOffOutside(StellaMove.ChrController.bounds.min.y - res.bounds.max.y); return(false); }
private void Awake() { LoadClearedStageCount(); PhysicsCaster.Init(); SelectedStage = Mathf.Min(clearedStageCount, StageMax - 1); if (SelectedStage == StageMax - 1) { SelectedStage = 0; } }
/// <summary> /// 移動先のチェックを行ってPushActionを呼び出します。 /// また、岩にめり込む対策のため、移動方向で埋まっていたら、埋まらない場所まで戻します。 /// </summary> /// <returns>戻す処理をしていたらtrueを返します。</returns> protected bool PushCheck() { float h = StellaMove.ChrController.height * 0.5f - StellaMove.ChrController.radius; int hitCount = PhysicsCaster.CharacterControllerCast( StellaMove.ChrController, StellaMove.forwardVector, Mathf.Abs(StellaMove.myVelocity.x * Time.fixedDeltaTime), PhysicsCaster.MapCollisionLayer); bool isBack = false; for (int i = 0; i < hitCount; i++) { Actable[] acts = PhysicsCaster.hits[i].collider.GetComponents <Actable>(); for (int j = 0; j < acts.Length; j++) { if (!acts[j].CanAction) { continue; } // 方向が左右か float ydif = PhysicsCaster.hits[i].point.y - StellaMove.ChrController.bounds.center.y; float sidecheck = h + StellaMove.ChrController.radius * 0.5f; if (Mathf.Abs(ydif) > sidecheck) { continue; } // 移動していて、移動先にオブジェクトがある場合、押す float to = PhysicsCaster.hits[i].collider.bounds.center.x - StellaMove.instance.transform.position.x; if (StellaMove.myVelocity.x * to > 0f) { StellaMove.ChrController.stepOffset = PushStepOffset; if (!acts[j].PushAction()) { continue; } } // 向いている方向に対象物がある時、対象物に触れていたらステラを下げる float range = StellaMove.ChrController.bounds.extents.x + PhysicsCaster.hits[i].collider.bounds.extents.x + StellaMove.CollisionMargin; if (((to * StellaMove.forwardVector.x) > 0f) && (Mathf.Abs(to) < range)) { float posx = PhysicsCaster.hits[i].collider.bounds.center.x - range * StellaMove.forwardVector.x; StellaMove.myVelocity.x = (posx - StellaMove.instance.transform.position.x) / Time.fixedDeltaTime; isBack = true; } } } return(isBack); }
/// <summary> /// 歩きから落下する時に、隣のブロックの中心辺りに着地できるようなX速度を設定 /// </summary> public void FallNextBlock() { // 着地目標のX座標を求める Vector3 origin = Vector3.zero; origin.x = Mathf.Round(StellaMove.instance.transform.position.x); // 着地目標のX座標と自分の足元のYから下方向にレイを飛ばして、着地点を見つける origin.y = StellaMove.ChrController.bounds.min.y; int cnt = PhysicsCaster.Raycast(origin, Vector3.down, float.PositiveInfinity, PhysicsCaster.MapCollisionPlayerOnlyLayer); if (cnt == 0) { #if UNITY_EDITOR // 本来ないはずだが念のため Debug.Log($"地面無し {cnt}"); #endif StellaMove.myVelocity.x = 0; return; } // 一番上を探す float top = PhysicsCaster.hits[0].collider.bounds.max.y; for (int i = 1; i < cnt; i++) { // 地面と水以外は対象外 if (!PhysicsCaster.hits[i].collider.CompareTag("Ground") && !PhysicsCaster.hits[i].collider.CompareTag("Water")) { continue; } if (PhysicsCaster.hits[i].collider.bounds.max.y > top) { top = PhysicsCaster.hits[i].collider.bounds.max.y; } } float h = StellaMove.ChrController.bounds.min.y - top; // 高さがないか、負の値の時は、1段分で算出 if (h <= 0f) { h = 1f; } float t = Mathf.Sqrt(2f * h / StellaMove.GravityAdd); StellaMove.myVelocity.x = (origin.x - StellaMove.instance.transform.position.x) / t; if (StellaMove.myVelocity.x * StellaMove.forwardVector.x < 0f) { StellaMove.myVelocity.x = 0; } }
/// <summary> /// 真下が岩以外なら、trueを返します、 /// </summary> bool NotOnRock() { int hitCount = PhysicsCaster.CharacterControllerCast(StellaMove.chrController, Vector3.down, getOffDistance, PhysicsCaster.MapCollisionLayer); for (int i = 0; i < hitCount; i++) { if (PhysicsCaster.hits[i].collider.CompareTag("Rock")) { return(false); } } return(true); }
/// <summary> /// ツタと重なっているかを確認します。重なっていたら、ツタのインスタンスを返します。 /// </summary> /// <returns>見つけたツタのインスタンス。なければnull</returns> static Ivy CheckIvyOverlap() { int hitCount = PhysicsCaster.CharacterControllerCast(ChrController, Vector3.down, 0f, PhysicsCaster.MapLayer, QueryTriggerInteraction.Collide); for (int i = 0; i < hitCount; i++) { Ivy ivy = PhysicsCaster.hits[i].collider.GetComponent <Ivy>(); if (ivy != null) { return(ivy); } } return(null); }
/// <summary> /// ツタが手の上にあればtrueを返します。 /// </summary> /// <returns>ツタが手の上にある時、true</returns> public static bool IsIvyUp() { // 上にツタがあるか? Vector3 origin = HoldPosition; origin.x = IvyInstance.BoxColliderInstance.bounds.min.x - 0.05f; origin.z = IvyInstance.transform.position.z; int hitCount = PhysicsCaster.Raycast(origin, Vector3.right, 0.1f, PhysicsCaster.NaeLayer, QueryTriggerInteraction.Collide); for (int i = 0; i < hitCount; i++) { if (PhysicsCaster.hits[i].collider.GetComponent <Ivy>() != null) { return(true); } } return(false); }
void FixedUpdate() { if (state == StateType.Spawn) { return; } switch (state) { case StateType.Fly: if (transform.position.y - startY > removeHeight) { Destroy(gameObject); } break; case StateType.Hold: lifeTime -= Time.fixedDeltaTime; if (lifeTime <= 0f) { state = StateType.Fall; Vector3 v = rb.velocity; v.Set(0f, fallSpeed, 0); rb.velocity = v; } break; case StateType.Fall: // 消す確認 Vector3 origin = boxCollider.bounds.center; origin.y = boxCollider.bounds.max.y; GameObject go = PhysicsCaster.GetGroundWater(origin, Vector3.up, 1f); if (go != null) { Destroy(gameObject); } break; } }
public override void UpdateAction() { // つた掴みチェック if (StellaMove.CheckIvyHold()) { return; } // 行動ボタンチェック。着地時は何もしない if (Input.GetButton("Action") && !isLanding) { Actable act = StellaMove.ActionBoxInstance.GetActableInstance(); if (act != null) { if (act.Action()) { return; } } } StellaMove.instance.Gravity(); StellaMove.instance.Move(); // 着地チェック bool isGrounded = StellaMove.ChrController.isGrounded; if (!isGrounded && (StellaMove.myVelocity.y < 0)) { int hitCount = PhysicsCaster.CharacterControllerCast( StellaMove.ChrController, Vector3.down, StellaMove.CollisionMargin, PhysicsCaster.MapCollisionPlayerOnlyLayer); for (int i = 0; i < hitCount; i++) { if (!PhysicsCaster.hits[i].collider.isTrigger) { isGrounded = true; } } } // 着地チェック if (!isLanding && isGrounded && StellaMove.myVelocity.y < 0f) { SoundController.Play(SoundController.SeType.Landing); StellaMove.myVelocity.x = 0; StellaMove.RegisterAnimEvent(Grounded); isLanding = true; StellaMove.CheckStepOn(); StageManager.SetFollowCameraTarget(StellaMove.instance.transform); } // 頭ぶつけチェック else if ((StellaMove.myVelocity.y > 0f) && StellaMove.IsHitHead) { SoundController.Play(SoundController.SeType.HitHead); StellaMove.myVelocity.y = 0f; } }
/// <summary> /// 移動先の高さをボックスコライダーでチェックして、必要ならミニジャンプします。 /// 移動していない時は、チェックしません。 /// </summary> public void CheckMiniJump() { Vector3 move = Vector3.zero; move.x = Input.GetAxisRaw("Horizontal"); if (Mathf.Approximately(move.x, 0f)) { return; } // 移動先に段差がないかを確認 float startOffset = ChrController.radius + boxColliderHalfExtents.x; checkCenter = ChrController.bounds.center + move * startOffset; float dist = (miniJumpCheckX - startOffset); int hitCount = PhysicsCaster.BoxCast(checkCenter, boxColliderHalfExtents, move, dist, PhysicsCaster.MapCollisionPlayerOnlyLayer); if (hitCount == 0) { return; } float footh = ChrController.bounds.min.y; int hitIndex = -1; float h = float.NegativeInfinity; for (int i = 0; i < hitCount; i++) { // ミニジャンプできないものは対象から外す Actable [] act = PhysicsCaster.hits[i].collider.GetComponents <Actable>(); if (act != null) { bool cantMiniJump = false; for (int j = 0; j < act.Length; j++) { if (!act[j].CanMiniJump) { Log($" cant MiniJump {PhysicsCaster.hits[i].collider.name}"); cantMiniJump = true; break; } } if (cantMiniJump) { continue; } } float temph = PhysicsCaster.hits[i].collider.bounds.max.y - footh; if (temph > h) { h = temph; hitIndex = i; } } if (hitIndex == -1) { return; } Log($" h={h} > {ChrController.stepOffset} and <= {miniJumpHeight}"); if ((h > ChrController.stepOffset) && (h <= miniJumpHeight)) { targetJumpGround = PhysicsCaster.hits[hitIndex].transform.position; targetJumpGround.y = ChrController.bounds.min.y + h; ChangeAction(ActionType.Jump); } }
public override void UpdateAction() { // キーの入力を調べる float h = Input.GetAxisRaw("Horizontal"); // 左右の移動速度(秒速)を求める StellaMove.myVelocity.x = h * StellaMove.MoveSpeed; StellaMove.instance.Gravity(); Log($"A: Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y} {StellaMove.myVelocity.x}, {StellaMove.myVelocity.y} rock={rockActable.transform.position.x}, {rockActable.transform.position.y}"); StellaMove.instance.Move(); Log($"B: Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y} isGrounded={StellaMove.chrController.isGrounded}"); // 逆再生設定 bool back = h * StellaMove.forwardVector.x < -0.5f; StellaMove.SetAnimBool("Back", back); if (!StellaMove.chrController.isGrounded) { /// 下に岩があればセーフ int hitCount = PhysicsCaster.CharacterControllerCast( StellaMove.chrController, Vector3.down, CheckFallHeight, PhysicsCaster.MapCollisionLayer); bool isRock = false; for (int i = 0; i < hitCount; i++) { if (PhysicsCaster.hits[i].collider.CompareTag("Rock")) { isRock = true; break; } } if (!isRock) { StellaMove.instance.ChangeAction(StellaMove.ActionType.Air); FallNextBlock(); Log($"C: Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y}"); } } else { // 真下が岩以外なら、他の行動へ if (NotOnRock()) { StellaMove.instance.ChangeToWalk(); Log($"D: Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y}"); } // 乗り換えチェック if (lastRockObject != StellaMove.stepOnObject) { Log($" 乗り換え"); lastRockObject = StellaMove.stepOnObject; rockActable = lastRockObject.GetComponent <RockActable>(); rockCollider = lastRockObject.GetComponent <SphereCollider>(); } // 岩に力を加える if (rockActable != null) { Vector3 lastPos = lastRockObject.transform.position; float dist = StellaMove.instance.transform.position.x - lastPos.x; if (dist < -changeDistance) { StellaMove.myVelocity.x = -rockSpeed[1]; } else if (dist > changeDistance) { StellaMove.myVelocity.x = rockSpeed[1]; } else { StellaMove.myVelocity.x = rockSpeed[0] * Mathf.Sign(dist); } // ステラが移動できるか確認 int hitCount = PhysicsCaster.CharacterControllerCast( StellaMove.chrController, StellaMove.myVelocity.x < 0f ? Vector3.left : Vector3.right, Mathf.Abs(StellaMove.myVelocity.x) * Time.fixedDeltaTime, PhysicsCaster.MapCollisionLayer); bool blocked = false; for (int i = 0; i < hitCount; i++) { if (PhysicsCaster.hits[i].collider.gameObject != lastRockObject) { // ぶつかるなら移動キャンセル StellaMove.myVelocity.x = 0f; blocked = true; break; } } // 岩を移動させる if (!blocked) { StellaMove.chrController.enabled = false; rockActable.PushAction(); Log($"F: Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y}"); // ステラの座標を修正する Vector3 stellaMove = Vector3.zero; float moved = lastRockObject.transform.position.x - lastPos.x; float rad = moved / rockCollider.radius; stellaMove.Set( moved + Mathf.Sin(rad) * rockCollider.radius, StellaMove.chrController.skinWidth * 1.5f, 0f); Log($" moved={moved}={lastRockObject.transform.position.x}-{lastPos.x} / rad={rad} / sin={Mathf.Sin(rad)} / rockrad={rockCollider.radius} / Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y}"); StellaMove.chrController.enabled = true; StellaMove.chrController.Move(stellaMove); Log($" moved2 Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y}"); // 着地 stellaMove.Set(0, -StellaMove.chrController.stepOffset, 0); StellaMove.chrController.Move(stellaMove); Log($"G: Stella={StellaMove.instance.transform.position.x}, {StellaMove.instance.transform.position.y} move={stellaMove.x}, {stellaMove.y} isGrounded={StellaMove.chrController.isGrounded} / rock={rockActable.transform.position.x}, {rockActable.transform.position.y}"); // 足元に岩が無ければ飛び降りる if (!CheckGetOff()) { Log($"H: {StellaMove.instance.transform.position}"); return; } } } // 操作していればジャンプチェック if (!Mathf.Approximately(h, 0f)) { StellaMove.instance.CheckMiniJump(); Log($"I: {StellaMove.instance.transform.position}"); } } }
public override void UpdateAction() { StellaMove.ZyouroEmitter.transform.position = StellaMove.ZyouroEmitterPosition.position; if (state == StateType.Action) { // 水オブジェクトを生成 if (Time.time - lastTriggerTime >= triggerEmitSeconds) { lastTriggerTime = Time.time; triggerObjects[triggerIndex].SetActive(true); triggerObjects[triggerIndex].transform.position = StellaMove.ZyouroEmitterPosition.position; triggerRigidbody[triggerIndex].velocity = StellaMove.ZyouroEmitter.forward * triggerSpeed; triggerWater[triggerIndex].Start(); triggerIndex = (triggerIndex + 1) % TriggerCount; } // 水まき終了チェック if (!Input.GetButton("Water") && (Grow.WaitGrowCount <= 0)) { // 水まき終了 state = StateType.End; StellaMove.SetAnimState(StellaMove.AnimType.Walk); StellaMove.RegisterAnimEvent(EndAction); zyouroParticle.Stop(); StellaMove.WaterSeStop(); return; } // 効果音 if ((Time.time - lastSeTime) >= waterSeSeconds) { lastSeTime = Time.time; StellaMove.WaterSePlay(); } // 後ずさりチェック int hitCount = PhysicsCaster.CharacterControllerCast(StellaMove.ChrController, Vector3.down, 0f, PhysicsCaster.MapCollisionPlayerOnlyLayer); for (int i = 0; i < hitCount; i++) { // 下げる float colx = PhysicsCaster.hits[i].collider.bounds.extents.x; float dist = StellaMove.ChrController.radius + colx + StellaMove.CollisionMargin; float target = PhysicsCaster.hits[i].transform.position.x - dist * StellaMove.forwardVector.x; float move = target - StellaMove.instance.transform.position.x; if (move * StellaMove.forwardVector.x >= 0f) { // 向いている方向には動かさない return; } StellaMove.myVelocity.x = move / Time.fixedDeltaTime; Vector3 lastPos = StellaMove.instance.transform.position; StellaMove.instance.Move(); lastPos.x = StellaMove.instance.transform.position.x; StellaMove.instance.transform.position = lastPos; StellaMove.myVelocity.x = 0f; } } else { StellaMove.instance.Gravity(); StellaMove.instance.Move(); } }