Skip to content

Instantly share code, notes, and snippets.

@satomi-i-k
Created October 2, 2023 06:55
Show Gist options
  • Save satomi-i-k/0e097381d99c908907bc13d821b55d57 to your computer and use it in GitHub Desktop.
Save satomi-i-k/0e097381d99c908907bc13d821b55d57 to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
using UnityEngine.EventSystems;
public class Raq_player : MonoBehaviour
{
// MonoBehaviorのクラスを継承しているため、publicの変数はInspectorに表示され動的に変えることができる。
// [HideInspector]で、外部クラスから値を参照するpublicの変数をInspectorに表示させないことができる
Vector3 target;
public Animator anim;
public Animator rangeCircle;
public Animator WiderangeCircle;
public Transform ball;
public Transform head;
public Transform lookAt;
public Transform opponent;
Vector3 startPos;
Vector3 startVelocity;
float startTime;
public float maxDragTime;
public float dragDistance;
public float speed;
public float timelag;
public float turnSpeed;
public float ballRange;
public float CeilingRange;
public float moveRange;
public float force;
public float upForce;
public float CeilingForce_y;
public float CeilingForce_z;
public float fowardForce;
public float swipeSensitivity;
public float frontwall_pos = 12.2f; // 前の壁のz座標の位置:ボールを打つ方向
float rotation;
float ball_player_dist;
bool move_action;
bool right;
bool canShoot;
bool shoot = true;
bool isInactive;
bool isHitting;
public Raq_GameManager raq_GameManager;
Raq_GameManager gamemanagerScript;
RubberBall ballScript;
// Start is called before the first frame update
void Start()
{
raq_GameManager = GameObject.FindObjectOfType<Raq_GameManager>();
gamemanagerScript = raq_GameManager.GetComponent<Raq_GameManager>();
ballScript = ball.GetComponent<RubberBall>();
isInactive = ball.GetComponent<RubberBall>().inactive;
rangeCircle.SetBool("Show", false);
WiderangeCircle.SetBool("Show", false);
isHitting = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0) && gamemanagerScript.playerServe && gamemanagerScript.befServe)
{
StartCoroutine(Player_Serve());
}
// set target as ball position
target = ball.position;
if (ball == null)
{
return;
}
if (!gamemanagerScript.befServe && !ballScript.GetLastHit() && !ballScript.after_hit)
{
//check if the player should move on the x axis
Raq_Move();
//check if the ball is in range
Raq_CheckBallRange(); // ボールをhitできる状態であればそれを画面上で示す
//check if we can shoot
if (rangeCircle.GetBool("Show") || WiderangeCircle.GetBool("Show"))
{
Raq_Shoot();
}
}
else if (ballScript.GetLastHit() && rangeCircle.GetBool("Show") || WiderangeCircle.GetBool("Show"))
{
rangeCircle.SetBool("Show", false);
WiderangeCircle.SetBool("Show", false);
}
}
void LateUpdate()
{
head.LookAt(lookAt.position);
}
IEnumerator Player_Serve()
{
anim.SetTrigger("Hit right");
yield return new WaitForSeconds(0.28f);
EventManager.Instance.TriggerRaqplayerServe();
ballScript.SetLastHit(true); // 最後に打った者をプレイヤーとして記録(アウト判定時の得点用)
}
//move left and right towards the target and update animations accordingly
void Raq_Move()
{
float target_dist = Vector3.Distance(transform.position, target);
move_action = target_dist > 0.1f && !rangeCircle.GetBool("Show");
if (move_action && !gamemanagerScript.befServe)
{
Vector3 move_target = new Vector3(target.x - 0.02f, -2.5f, target.z);
transform.position = Vector3.MoveTowards(transform.position, move_target, Time.deltaTime * speed * 0.6f); // new player's position after moving
right = target.x < transform.position.x; // from opponent's view
}
if (anim.GetBool("Right") != right && !gamemanagerScript.befServe) // 右に行くべきなのにアニメーションが右方向への移動ではない
{
anim.SetBool("Right", right); // 右に行くアニメーションにセット
}
if (gamemanagerScript.befServe)
{
rotation = 0;
}
else
{
if (right)
{
rotation = -90;
}
else
{
rotation = 91;
}
}
anim.SetBool("Moving", move_action && !gamemanagerScript.befServe); // 移動アニメーションにセット
Vector3 rot = transform.eulerAngles; // eulerAngles: オイラー角、絶対位置上の角度
rot.y = rotation; // プレイヤーの方向を先ほどセットしたrotationの角度にするため
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(rot), Time.deltaTime * turnSpeed); // 現在のrotationの値から先ほど更新した新しいrotationの値の角度に向かって Time.deltaTime * turnSpeed 回転
}
//check if we can hit the ball
void Raq_CheckBallRange()
{
if (ball == null)
{
ball_player_dist = 0;
}
else
{
ball_player_dist = Vector3.Distance(transform.position, ball.position);
}
if (ball_player_dist < ballRange && !isInactive) // ボールとプレイヤーの距離差が一定以下、ballがinactiveでない
{
Raq_CanHitBall(); // ボールをhitできる状態であることを画面上で示すための関数
if (WiderangeCircle.GetBool("Show"))
{
WiderangeCircle.SetBool("Show", false);
}
}
else if (ball_player_dist < CeilingRange && !isInactive) // ボールとプレイヤーの距離差がシーリングが打てる状況
{
Raq_CanCeilingShot(); // シーリングショットできる状態を画面上で示すための関数
if (rangeCircle.GetBool("Show"))
{
rangeCircle.SetBool("Show", false);
}
}
else if (rangeCircle.GetBool("Show") || WiderangeCircle.GetBool("Show"))
{
rangeCircle.SetBool("Show", false); // アニメーションの変更
WiderangeCircle.SetBool("Show", false);
}
}
//if the ball is close enough, show the range circle
void Raq_CanHitBall()
{
if (rangeCircle.GetBool("Show")) // rangeCircleのアニメーションがshowになっていれば終了、なっていなければshowに変える
return;
rangeCircle.SetBool("Show", true);
}
//if the ball is not close but can ceiling shot, show another range circle
void Raq_CanCeilingShot()
{
if (WiderangeCircle.GetBool("Show")) // WiderangeCircleのアニメーションがshowになっていれば終了、なっていなければshowに変える
return;
WiderangeCircle.SetBool("Show", true);
}
// checks for swipe motion to see if we want to shoot the ball // 条件に合致すればRaq_Hit(currentPos)を発動
void Raq_Shoot()
{
Vector3 currentPos = Input.mousePosition;
if (Input.GetMouseButtonDown(0) && shoot) // ユーザーが左クリックしていればtrue、swipeがshootと扱われるための入口
{
canShoot = true;
startPos = currentPos; // 初期のマウス位置
startTime = Time.time; // フレームの開始時間
if (ball != null)
{
// startVelocity = ball.GetComponent<Rigidbody>().velocity;
// ball.GetComponent<Rigidbody>().isKinematic = true;
}
}
else if (Input.GetMouseButton(0) && canShoot)
{
if (Time.time - startTime > maxDragTime) // maxDragTimeはスワイプをshootとして判定する閾値、ドラッグの動きが遅いとshootにはならない
{
Raq_ResetShot();
}
else if (Vector3.Distance(startPos, currentPos) > dragDistance && !isHitting) // dragDistanceもスワイプをshootとして判定する閾値(距離だからfloat)。スワイプ距離が十分ならshootになる。
{
Raq_Hit(currentPos);
isHitting = true;
}
}
else if (Input.GetMouseButtonUp(0) && canShoot) // ユーザーが左クリックを離していればtrue
{
Raq_ResetShot();
}
}
//reset checks for swipe if swipe wasn't correct
void Raq_ResetShot()
{
isHitting = false;
canShoot = false; // 入口に戻る
}
//hit the ball
void Raq_Hit(Vector3 currentPos)
{
anim.SetTrigger("Hit right");
//use the swipe to check the ball direction
float difference_x = currentPos.x - startPos.x; // マウスの移動距離(Shoot()が実行された時の差分)
float xPos = swipeSensitivity * -difference_x; // マウスの移動距離に係数をかける
float difference_y = currentPos.y - startPos.y;
float yPos = swipeSensitivity * -difference_y;
xPos = Mathf.Clamp(xPos, -moveRange, moveRange); // xPosの値の範囲を-制限し、一定以上の動きは同じものとして扱う
yPos = Mathf.Clamp(yPos, -moveRange, moveRange);
// ボールの移動先のベクトル
Vector3 random = new Vector3(xPos, yPos + ball.position.y, frontwall_pos) ; // 元のスクリプトではy=0. 後のvelocityの計算でy座標に一定の値が加えられている。これらを踏まえて確認。
Vector3 direction = (random - transform.position).normalized; // プレイヤーがボールを打った方向の単位ベクトル
//check if this is the serve, or if we're just hitting the ball during the game and set the ball velocity
if (rangeCircle.GetBool("Show"))
{
direction = new Vector3(direction.x * force, direction.y + upForce, direction.z * force * fowardForce);
}
else if (WiderangeCircle.GetBool("Show"))
{
direction = new Vector3(direction.x * force, direction.z * force * CeilingForce_y, direction.z * force * CeilingForce_z);
}
EventManager.Instance.TriggerRaqplayerHit(direction);
ballScript.SetLastHit(true); // 最後に打った者をプレイヤーとして記録(アウト判定時の得点用)
}
//stop shooting for .7 seconds
IEnumerator Raq_DisableShooting()
{
shoot = false;
yield return new WaitForSeconds(.7f);
shoot = true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment