Skip to content

Instantly share code, notes, and snippets.

@ryogrid
Created November 16, 2023 23:41
Show Gist options
  • Save ryogrid/8f9d717c694dbbc1bb673c31e9346999 to your computer and use it in GitHub Desktop.
Save ryogrid/8f9d717c694dbbc1bb673c31e9346999 to your computer and use it in GitHub Desktop.
Unityで作った3D版Pongのソースコード部分だけ (https://unityroom.com/games/3dpongmodoki)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallController : MonoBehaviour
{
public GameObject StampPrefab;
public GameObject ParticlePrefab;
private Rigidbody rb;
private GameObject BallZLine;
private GameObject BallZLineHorizontal;
private GameObject BallZLineVertical;
private Vector3 lastVelocity;
private Vector3 lastPosition;
private int counter = 0;
public static float Z_CONSTANT_VELOCITY = 2.5f;
private const float Z_CONSTANT_HALF_VELOCITY = 1.25f;
private const float Z_STRANGE_VELOCITY_THRESHOLD = 0.1f;
private const float XY_VELOCITY_LATIO_UPPER = 1f;
private const float XY_VELOCITY_LATIO_BOTTOM = 0.2f;
private AudioSource audioSource;
public AudioClip audioBound;
private const int COUNTER_ADJUST_THRESHOLD = 5;
private GameObject createdParticle = null;
// Start is called before the first frame update
void Start()
{
lastVelocity = new Vector3(0, 0, 0);
rb = this.GetComponent<Rigidbody>();
BallZLine = GameObject.Find("BallZLine");
BallZLineHorizontal = GameObject.Find("BallZLineHorizontal");
BallZLineVertical = GameObject.Find("BallZLineVertical");
audioSource = gameObject.GetComponent<AudioSource>();
}
//一定秒数ごとに呼び出される. デフォルトは20ms間隔らしい
void FixedUpdate()
{
if (counter > COUNTER_ADJUST_THRESHOLD)
{
//ボールのスピードをいい感じに調整する
adjustBallSpeed();
}
//異様に速度が遅くなっている場合はその速度は採用しない
if(Mathf.Abs(rb.velocity.z) >= Z_CONSTANT_HALF_VELOCITY || counter < COUNTER_ADJUST_THRESHOLD)
{
lastVelocity = rb.velocity;
}
//iTween.MoveTo(BallZLine, iTween.Hash("x", this.transform.position.x, "y", this.transform.position.y));
BallZLine.transform.position = new Vector3(this.transform.position.x, this.transform.position.y, 0);
BallZLineHorizontal.transform.position = new Vector3(0, this.transform.position.y, this.transform.position.z);
BallZLineVertical.transform.position = new Vector3(this.transform.position.x, 0, this.transform.position.z);
}
private void resetBallZLine()
{
BallZLine.transform.position = new Vector3(0, 0, 0);
BallZLineHorizontal.transform.position = new Vector3(0, 0, 0);
BallZLineVertical.transform.position = new Vector3(0, 0, 0);
}
private void adjustBallSpeed()
{
float vx = rb.velocity.x;
float vy = rb.velocity.y;
float vz = rb.velocity.z;
float vz_abs = Mathf.Abs(vz);
if (vz_abs <= Z_STRANGE_VELOCITY_THRESHOLD && counter > COUNTER_ADJUST_THRESHOLD) {
// 突き抜け等の可能性があるため必ず手前方向に移動させる
vz_abs = Z_CONSTANT_VELOCITY;
vz = -1 * Z_CONSTANT_VELOCITY;
}
if (vz_abs < Z_CONSTANT_VELOCITY){
vz_abs = Z_CONSTANT_VELOCITY;
vz = vz >= 0 ? Z_CONSTANT_VELOCITY : -1 * Z_CONSTANT_VELOCITY;
}
if(Mathf.Abs(vx) >= XY_VELOCITY_LATIO_UPPER * vz_abs)
{
vx = vx >= 0 ? XY_VELOCITY_LATIO_UPPER * vz_abs : -1 * XY_VELOCITY_LATIO_UPPER * vz_abs;
}
if(Mathf.Abs(vx) <= XY_VELOCITY_LATIO_BOTTOM * vz_abs)
{
vx = vx >= 0 ? XY_VELOCITY_LATIO_BOTTOM * vz_abs : -1 * XY_VELOCITY_LATIO_BOTTOM * vz_abs;
}
if(Mathf.Abs(vy) >= XY_VELOCITY_LATIO_UPPER * vz_abs)
{
vy = vy >= 0 ? XY_VELOCITY_LATIO_UPPER * vz_abs : -1 * XY_VELOCITY_LATIO_UPPER * vz_abs;
}
if(Mathf.Abs(vy) <= XY_VELOCITY_LATIO_BOTTOM * vz_abs)
{
vy = vy >= 0 ? XY_VELOCITY_LATIO_BOTTOM * vz_abs : -1 * XY_VELOCITY_LATIO_BOTTOM * vz_abs;
}
rb.velocity = new Vector3(vx, vy, vz);
}
// Update is called once per frame
void Update()
{
if (transform.position.z < -3f)
{
resetBallZLine();
Destroy(gameObject);
}
counter += 1;
if((lastPosition == null || counter % 11 == 0))
{
lastPosition = gameObject.transform.position;
}
if (counter % 17 == 0 && lastPosition.x == gameObject.transform.position.x && lastPosition.y == gameObject.transform.position.y && lastPosition.z == gameObject.transform.position.z
&& rb.velocity.x == 0 && rb.velocity.x == 0 && rb.velocity.z == 0){
resetBallZLine();
Destroy(gameObject);
}
}
void createStamp(Collision coll)
{
float x = gameObject.transform.position.x;
float y = gameObject.transform.position.y;
float z = gameObject.transform.position.z;
//当たり判定が発生した座標
Vector3 contactCood = coll.GetContact(0).point;
float cx = contactCood.x;
float cy = contactCood.y;
float cz = contactCood.z;
GameObject wall = coll.gameObject;
float wx = wall.transform.position.x;
float wy = wall.transform.position.y;
float wz = wall.transform.position.z;
// 0.1fは差が明確にあることを判定するために適当に選んだ閾値
if(createdParticle != null)
{
Destroy(createdParticle);
}
if(Mathf.Abs(cx) - Mathf.Abs(x) > 0.1f) //左右の壁
{
GameObject obj = Instantiate(StampPrefab, new Vector3(wx, y, z), Quaternion.identity);
createdParticle = Instantiate(ParticlePrefab, new Vector3(cx, y, z), Quaternion.identity);
obj.transform.rotation = Quaternion.Euler(0, 0, 90) * obj.transform.rotation;
return;
}
if(Mathf.Abs(cy) - Mathf.Abs(y) > 0.1f) //上下の壁
{
GameObject obj = Instantiate(StampPrefab, new Vector3(x, wy, z), Quaternion.identity);
createdParticle = Instantiate(ParticlePrefab, new Vector3(x, cy, z), Quaternion.identity);
return;
}
if(Mathf.Abs(cz) - Mathf.Abs(z) > 0.1f) //奥の壁もしくはラケット
{
if(z > 0) //奥の壁
{
GameObject obj = Instantiate(StampPrefab, new Vector3(x, y, wz), Quaternion.identity);
createdParticle = Instantiate(ParticlePrefab, new Vector3(x, y, cz), Quaternion.identity);
obj.transform.rotation = Quaternion.Euler(90, 0, 0) * obj.transform.rotation;
return;
}
else //ラケット
{
GameObject obj = Instantiate(StampPrefab, new Vector3(x, y, wz), Quaternion.identity);
//薄くする
obj.transform.localScale = new Vector3(0.3f, 0.001f, 0.3f);
obj.transform.rotation = Quaternion.Euler(90, 0, 0) * obj.transform.rotation;
return;
}
}
}
void OnCollisionEnter(Collision coll)
{
Vector3 refrectVec = Vector3.Reflect(this.lastVelocity, coll.contacts[0].normal);
//Debug.Log(refrectVec);
refrectVec.x *= 1.01f;
refrectVec.y *= 1.01f;
refrectVec.z *= 1.01f;
rb.velocity = refrectVec;
createStamp(coll);
audioSource.PlayOneShot(audioBound);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class KeyCheckerControler : MonoBehaviour
{
public GameObject BallPrefab;
public GameObject RacketPrefab;
private GameObject ScoreText;
private GameObject createdBall = null;
private GameObject createdRacket = null;
private GameObject RacketZLineHorizontal = null;
private GameObject RacketZLineVertical = null;
private const float CHECK_INTERVAL = 0.01f;
private const float MOVE_DISTANCE = 0.05f;
private const float PIXCELS_OF_UNIT = 100f;
// Start is called before the first frame update
void Start()
{
createdRacket = Instantiate(RacketPrefab, new Vector3(0, 0, -2f), Quaternion.identity);
ScoreText = GameObject.Find("ScoreMeshText");
ScoreText.GetComponent<TextMesh>().text = "0 回";
RacketZLineHorizontal = GameObject.Find("RacketZLineHorizontal");
RacketZLineVertical = GameObject.Find("RacketZLineVertical");
//createdRacket.GetComponent<Renderer>().material.color = Color.blue;
InvokeRepeating("checkKeyPress", CHECK_INTERVAL, CHECK_INTERVAL);
}
// Update is called once per frame
void Update()
{
}
float getConvertedMouseCoodX()
{
return ((Input.mousePosition.x / Screen.width) * 5f - 2.5f) * 1.3f;
}
float getConvertedMouseCoodY()
{
return (Input.mousePosition.y / Screen.height) * 5f - 2.5f;
}
void checkKeyPress()
{
createdRacket.transform.position = new Vector3 (getConvertedMouseCoodX(), getConvertedMouseCoodY(), createdRacket.transform.position.z);
if (Input.GetKeyDown(KeyCode.Space))
{
shotNewBall();
}
RacketZLineHorizontal.transform.position = new Vector3(0, createdRacket.transform.position.y, createdRacket.transform.position.z);
RacketZLineVertical.transform.position = new Vector3(createdRacket.transform.position.x, 0, createdRacket.transform.position.z);
}
private void reCreateRacket()
{
if(createdRacket != null)
{
Destroy(createdRacket);
createdRacket = null;
}
createdRacket = Instantiate(RacketPrefab, new Vector3(0, 0, -2f), Quaternion.identity);
}
void shotNewBall()
{
if (createdBall != null)
{
return;
}
createdBall = Instantiate(BallPrefab, new Vector3(0, 0, -1.5f), Quaternion.identity);
float shotVerocityFixedZ = BallController.Z_CONSTANT_VELOCITY;
float shotAngle = Random.Range(0f, 360f);
float x_speed = Mathf.Cos(2 * Mathf.PI * (shotAngle / 360f)) * shotVerocityFixedZ;
float y_speed = Mathf.Sin(2 * Mathf.PI * (shotAngle / 360f)) * shotVerocityFixedZ;
createdBall.GetComponent<Renderer>().material.color = Color.black;
//createdBall.GetComponent<Rigidbody>().AddForce(new Vector3(x_power, y_power, shotVerocityFixedZ));
createdBall.GetComponent<Rigidbody>().velocity = new Vector3(x_speed, y_speed, shotVerocityFixedZ);
//createdBall.GetComponent<Rigidbody>().AddForce(new Vector3(0, 0, shotPowerFixedZ));
ScoreText.GetComponent<TextMesh>().text = "0 回";
//内部状態を初期化するために作り直す
reCreateRacket();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RacketController : MonoBehaviour
{
private int BoundCount;
// Start is called before the first frame update
void Start()
{
BoundCount = 0;
}
// Update is called once per frame
void Update()
{
}
void OnCollisionEnter(Collision collision)
{
BoundCount++;
GameObject.Find("ScoreMeshText").GetComponent<TextMesh>().text = BoundCount.ToString() + " 回";
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StampController : MonoBehaviour
{
private int counter = 0;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//if(counter > 50)
if(counter > 15)
{
Destroy(gameObject);
return;
}
counter++;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment