LoginSignup
2
2

More than 3 years have passed since last update.

[Unity]Unityの機能を使わずにゲームを作る(自作物理演算,自作当たり判定,自作アニメーション,自作マップスクロール,自作パーティクルシステム)

Last updated at Posted at 2019-12-23

このゲームには以下の要素が含まれます

  • 自作物理演算
  • 自作当たり判定
  • 自作アニメーション
  • 自作マップスクロール
  • 自作パーティクルシステム

総じてゲームアニメーションプログラミング

ゲームアニメーションプログラミングで検索したらこの記事が出てきて救済を求めてクリックした
そこのあなた
筆者はあなたの先輩説あります

なんでこんなことしてるって

そういう条件で提出するものだったもんで
要はProcessingでやるのが普通だけどUnityの機能使わなければUnityでもいいよって言われたからやりました

それではやっていきましょう

実行結果

GapInterMediate.gif

スクリプト

作成したスクリプトをどばっと紹介
説明はプログラムにコメントあるから省略

アニメーションクラス

Anim.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// アニメーションクラス
/// </summary>
public class Anim : MonoBehaviour
{
    [SerializeField,Tooltip("アニメーションの更新時間")] float updateTime = 0;
    [SerializeField,Tooltip("アニメーション")] Sprite[] anims = null;
    //画像表示クラス
    SpriteRenderer sr;
    float time = 0;
    [System.NonSerialized]public int num;

    void Awake()
    {
        sr = GetComponent<SpriteRenderer>();
        if (anims == null || anims.Length == 0)
        {
            enabled = false;
            return;
        }
    }
    void OnEnable()
    {
        sr.sprite = anims[0];
    }

    //任意のタイミングでアニメーション
    public void Updater()
    {
        time += Time.deltaTime;
        if(time >= updateTime)
        {
            time = 0;
            sr.sprite = anims[num++];
            if (num >= anims.Length) num = 0;
        }
    }
    public void ChangePic(int n)
    {
        num = n;
        sr.sprite = anims[num];
    }
}

矢の動きクラス

Arrow.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 矢コントローラー
/// </summary>
public class Arrow : Col
{
    [SerializeField] Parts isGroundEffect = null;
    public float Speed { get; set; }
    Rigider rigid;
    Rect range = new Rect(0, 0, 1, 1);
    bool prevGrounded = true;

    void Start()
    {
        rigid = GetComponent<Rigider>();
        Manager.AddArrows(this);
        rigid.velocity = Vector3.zero;
        rigid.AddForce(transform.right * Speed);
    }

    void Update()
    {
        if (rigid.enabled)
        {
            if (rigid.isGround && !prevGrounded) //着地した瞬間
            {
                rigid.enabled = false;
                RemoveList();//当たり判定削除
                Vector3 pos = transform.position;
                pos.y = 0;
                Parts p = Instantiate(isGroundEffect, pos, Quaternion.identity,transform);
                p.maxParticles = (int)Speed/2;
                p.particleSpeed = Speed/10f;
                p.effectTime = 0.01f * Speed;


                Destroy(gameObject, 10);
            }
            prevGrounded = rigid.isGround;
        }

        //落ちる回転モーション
        transform.rotation = Quaternion.AngleAxis(
            Mathf.Atan2(rigid.velocity.y, rigid.velocity.x) * Mathf.Rad2Deg,
            Vector3.forward);
    }

    void RemoveList()
    {
        Manager.RemoveArrows(this);
    }
    public override void OnHit()
    {
        RemoveList();
        //当たり判定でのエラー対策として1秒後に削除
        Destroy(gameObject, 0.1f);
    }
}

拝啓 背景スクロールクラス様

Backgrounder.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 背景スクロール調整クラス
/// </summary>
public class Backgrounder : MonoBehaviour
{
    [SerializeField,Tooltip("0~1で背景が動く倍率を変化させる")]
    float ratio = 0;
    [SerializeField,Tooltip("ワープする距離")]
    float transDist = 0;
    float maxPlayerDist = 0;//ワープ条件の距離
    float timer = 1;
    float dist = 0;

    void Start()
    {
        maxPlayerDist = transDist / 2;
    }

    void Update()
    {
        //プレイヤーの移動方向によって左右移動
        transform.position +=
            (Vector3.right * Director.cameraDirection) * ratio * Time.deltaTime;

        //一定時間毎に距離計測
        timer += Time.deltaTime;
        if (timer > 0.4)
        {
            timer = 0;
            dist = Camera.main.transform.position.x - transform.position.x;

            if (Mathf.Abs(dist) >= maxPlayerDist)//指定距離離れたらテレポート
            {
                Vector3 treePosition = transform.position;
                treePosition.x += transDist * Mathf.Sign(dist);
                transform.position = treePosition;
            }
        }
    }
}

当たり判定クラス

Col.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 当たり判定クラス
/// </summary>
public class Col : MonoBehaviour
{
    //当たり判定半径
    public float radius;
    //位置調整
    public Vector3 offset;
    /// <summary>
    /// 当たり判定
    /// </summary>
    /// <param name="col">検証コライダー</param>
    /// <returns>是非</returns>
    public bool CheckHit(Col col)
    {
        return (transform.position + offset - col.transform.position + col.offset).sqrMagnitude
            < (radius + col.radius) * (radius + col.radius);
    }
    /// <summary>
    /// 衝突時に呼ばれる関数
    /// </summary>
    public virtual void OnHit()
    {
        print(gameObject.name);
    }

    /// <summary>
    /// 破壊アニメーション
    /// </summary>
    /// <returns></returns>
    protected IEnumerator DestroyCoroutine()
    {
        //マテリアル取得
        Material mat = GetComponentInChildren<SpriteRenderer>().material;
        float t = 0;
        //シェーダを利用した破壊アニメーション
        while (t < 1)
        {
            mat.SetFloat("_Threshold", t);
            t += Time.deltaTime * 2;
            yield return null;
        }

        Destroy(gameObject);
    }
}

ゲーム管理クラス

Director.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

/// <summary>
/// ゲーム管理者
/// </summary>
public class Director : MonoBehaviour
{
    [SerializeField,Tooltip("的")] GameObject target = null;
    [SerializeField,Tooltip("スコア表示テキスト")] Text scoreText = null;
    [SerializeField, Tooltip("時間表示テキスト")] Text timeText = null;
    public UnityEvent toResult; //結果表示イベント
    public static float cameraDirection = 0; //カメラが動く方向
    int score = 0;
    int nowScore = 0;
    float timer = 0;
    float time = 0;
    float countDown = 0;
    Coroutine scoreCoroutine = null;
    int mode = 0;

    void Update()
    {
        if(mode == 1)
        {
            //的生成
            time += Time.deltaTime;
            if (time >= timer)
            {
                time = 0;
                RandomTime();
                InstTarget();
            }

            //カウントダウン
            countDown -= Time.deltaTime;
            if((int)countDown <= 0)
            {
                toResult.Invoke();
            }
            timeText.text = (int)countDown + "";
        }

    }
    void GameStart()
    {
        time = 0;
        nowScore = score = 0;
        countDown = 30;
        RandomTime();
        InstTarget();
        Point(0);
    }
    void RandomTime()
    {
        timer = Random.Range(1, 5);
    }
    void InstTarget()
    {
        //カメラより先の場所で的生成
        Instantiate(target,
            Camera.main.transform.position + Vector3.right * 35,
            Quaternion.identity);
    }

    public void Point(int point)
    {
        if (mode != 1) return;
        score += point * 10;
        if (scoreCoroutine == null)
            scoreCoroutine = StartCoroutine(Scorerer());
    }
    //スコアが変化するコルーチン
    IEnumerator Scorerer()
    {
        while (nowScore <= score)
        {
            scoreText.text = "Score:" + nowScore++;
            yield return null;
        }
        scoreCoroutine = null;
    }
    //インスペクタから参照
    public void ChangeMode(int mode)
    {
        this.mode = mode;
        switch (mode)
        {
            case 0:
                break;

            case 1:
                GameStart();
                break;

            case 2:
                break;
        }
    }
}

当たり判定マネージャークラス

Manager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 当たり判定検証クラス
/// </summary>
public class Manager : MonoBehaviour
{
    [SerializeField] Director director = null;
    //当たり判定検証用の矢と的のリスト
    static List<Col> arrows = new List<Col>();
    static List<Col> targets = new List<Col>();
    //削除用の矢と的のリスト
    static List<Col> removeArrows = new List<Col>();
    static List<Col> removeTargets = new List<Col>();
    static List<Col> hitTargets = new List<Col>();
    int arrowsNum = 0;
    private void Update()
    {
        if (arrows.Count > 0)
        {
            //全ての的に対し、arrowsNum 番の矢との当たり判定検証
            for (int i = 0; i < targets.Count; i++)
            {
                if (targets[i].CheckHit(arrows[arrowsNum]))
                {
                    targets[i].OnHit();
                    arrows[arrowsNum].OnHit();
                }
            }
            arrowsNum++;
        }
        if(removeArrows.Count > 0)
        {
            foreach (Col c in removeArrows)
                arrows.Remove(c);

            removeArrows.Clear();
        }
        if(removeTargets.Count > 0)
        {
            foreach (Col c in removeTargets)
                targets.Remove(c);

            removeTargets.Clear();
        }
        if(hitTargets.Count > 0)
        {
            int total = 0;
            foreach(Col c in hitTargets)
            {
                targets.Remove(c);
                total += ((Target)c).point;
            }
            //スコアを反映
            director.Point(total);
            hitTargets.Clear();
        }  

        //矢のカウントをリセット
        if (arrowsNum >= arrows.Count) arrowsNum = 0;

    }

    public static void AddArrows(Col c)
    {
        arrows.Add(c);
    }

    public static void AddTargets(Col c)
    {
        targets.Add(c);
    }

    public static void RemoveArrows(Col c)
    {
        removeArrows.Add(c);
    }

    public static void RemoveTargets(Col c)
    {
        removeTargets.Add(c);
    }

    public static void HitTargets(Col c)
    {
        hitTargets.Add(c);
    }
}

カメラ追従クラス

MoveCamera.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// カメラ移動クラス
/// </summary>
public class MoveCamera : MonoBehaviour
{
    //追従対象
    public Transform target;

    void Update()
    {
        //滑らかに追従
        transform.position = Vector3.Lerp(
            transform.position, 
            new Vector3(target.position.x,target.position.y,transform.position.z),
            Time.deltaTime);
        //カメラの移動方向を代入
        Director.cameraDirection = target.position.x - transform.position.x;
    }
}

パーティクルシステム

Parts.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// パーティクルクラス
/// </summary>
public class  Parts : MonoBehaviour
{
    [SerializeField,Tooltip("生成物")] Transform obj = null;
    [Tooltip("ループ")]
    public bool loop = false;
    [Tooltip("重力")]
    public bool isGravity = false;
    [Tooltip("重力値")]
    public float gravity = -0.1f;
    [Tooltip("跳ねるか")]
    public bool bounds = false;
    [Tooltip("最大パーティクル数")]
    public int maxParticles = 20;
    [Tooltip("エフェクトの余命")]
    public float effectTime = 1;
    [Tooltip("パーティクルの余命")]
    public float particlesLifeTime = 1;
    [Tooltip("パーティクルの速度")]
    public float particleSpeed = 1;
    [Tooltip("パーティクルの初ランダム回転")]
    public bool randomRotate = false;
    [Tooltip("パーティクルの回転")]
    public float particleRotate = 0;
    [Tooltip("パーティクル生成最小頻度")]
    public float minTimeInst = 0.01f;
    [Tooltip("パーティクルはランダムサイズ")]
    public bool randomSize = false;

    P[] ps;
    int tale = 0;
    float time = 0;
    float timer = 0;
    float effectTimer = 0;

    /// <summary>
    /// 次に使うパーティクルの位置を返す
    /// </summary>
    int Get { get {
            tale++;
            return tale % maxParticles; 
        } 
    }

    void Start()
    {
        ps = new P[maxParticles];
        for(int i = 0; i < maxParticles; i++)
        {
            float size = (randomSize ? Random.value : 1);
            Instantiate(obj, //生成オブジェ
                transform.position,//位置  回転↓
           (randomRotate ? Quaternion.Euler(0, 0, Random.Range(0, 360)) : Quaternion.identity),
                transform)//親オブジェ
                .localScale = new Vector3(size,size);

            ps[i] = new P(Random.value + particleSpeed);
        }
        tale = maxParticles / 10;
        //1割は開始
        for (int i = 0; i < tale; i++)
            transform.GetChild(i).gameObject.SetActive(true);
        time = Random.Range(0, 0.2f);
    }

    void Update()
    {
        InstParticles();

        Transform t;
        for(int i = 0; i < transform.childCount; i++)
        {
            //子オブジェの中からアクティブなのを探す
            if (transform.GetChild(i).gameObject.activeSelf)
            {
                t = transform.GetChild(i);

                ps[i].time += Time.deltaTime;
                if (ps[i].time > particlesLifeTime)
                {
                    ps[i].time = 0;
                    t.gameObject.SetActive(false);
                    continue;
                }

                if(isGravity)ps[i].direY += gravity;
                //パーティクルの移動
                t.position += new Vector3(ps[i].direX * Time.deltaTime, ps[i].direY * Time.deltaTime) ;
                //パーティクルの回転
                t.Rotate(0,0,particleRotate * Time.deltaTime);
                if (bounds) 
                    if (t.position.y <= 0)
                    {
                        t.position = new Vector3(t.position.x, 0, 0);
                        ps[i].direY *= -1;
                    }
            }
        }

    }

    /// <summary>
    /// パーティクル生成
    /// </summary>
    void InstParticles()
    {
        effectTimer += Time.deltaTime;
        if (!loop && effectTimer >= effectTime)//エフェクトの寿命
        {
            //パーティクルが生存なら待つ
            foreach (Transform t in transform)
                if (t.gameObject.activeSelf) return;
            //パーティクルなしなら削除
            Destroy(gameObject);
        }
        else if (loop || tale < maxParticles)//寿命までは生成
        {
            timer += Time.deltaTime;
            if (timer >= time)
            {
                timer = 0;
                //次の生成までの時間をランダムで設定
                time = Random.Range(minTimeInst, 0.2f);
                int num = Get;
                transform.GetChild(num).gameObject.SetActive(true);
                transform.GetChild(num).position = transform.position;
            }
        }
    }

    /// <summary>
    /// パーティクルの移動方向と寿命を管理
    /// </summary>
    class P
    {
        public float direX = 0;
        public float direY = 0;
        public float time = 0;
        public P(float speed)
        {
            direX = Random.Range(-1,1f) * speed;
            direY = Random.Range(-1, 1f) * speed;
            time = 0;
        }
    }
}

プレイヤークラス

Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// プレイヤーコントローラー
/// </summary>
public class Player : MonoBehaviour
{
    [SerializeField,Tooltip("移動速度")] float speed = 1;
    [SerializeField,Tooltip("移動アニメーション")] Anim animMove = null;
    [SerializeField,Tooltip("停止画像")] SpriteRenderer animStop = null;
    [SerializeField,Tooltip("ジャンプアニメーション")] Anim animJump = null;
    [SerializeField,Tooltip("矢継ぎアニメーション")] Anim animShot = null;
    [SerializeField,Tooltip("腕の回転位置")] Transform armJoint = null;
    [SerializeField,Tooltip("生成矢")] Arrow arrow = null;
    [SerializeField, Tooltip("最大エフェクト")] Parts maxPowEffect = null;
    //重力
    Rigider rigid;
    Parts powEffect = null;
    float power = 0;
    enum Mode
    {
        Stop, Walk, Jump
    }
    Mode mode = Mode.Stop;

    void Start()
    {
        rigid = GetComponent<Rigider>();
    }

    void Update()
    {
        InputCheck();

        AnimUpdate();

        RotateArm();
    }

    void InputCheck()
    {
        float dire = 0;

        //右矢印入力
        if (Input.GetKey(KeyCode.RightArrow))
        {
            dire = speed;
            mode = Mode.Walk;
        }
        //左矢印入力
        else if (Input.GetKey(KeyCode.LeftArrow))
        {
            dire = -speed;
            mode = Mode.Walk;
        }

        if (rigid.isGround)//地に足のついた
        {
            if (dire == 0) //移動していないならSTOP
            {
                mode = Mode.Stop;
            }
            //上矢印入力
            if (Input.GetKey(KeyCode.UpArrow))
            {
                mode = Mode.Jump;

                //移動
                rigid.AddForce(new Vector3(0,25));
            }
        }
        else//空中
        {
            mode = Mode.Jump;
            animJump.ChangePic(rigid.velocity.y > 0 ? 0 : 1);
        }

        //マウスクリック
        if (Input.GetMouseButton(0))
        {
            if (power < 1)
                power += Time.deltaTime;
            else
            {
                power = 1;
                if (powEffect == null) 
                    powEffect = Instantiate(maxPowEffect,
                        armJoint.position, Quaternion.identity,
                        transform);
            }
            //長押しの時間で表示する画像を変更
            animShot.ChangePic((int)(power * 10));
        }
        else if (Input.GetMouseButtonUp(0))
        {
            //矢を生成
            Arrow a = Instantiate(arrow, armJoint.position + armJoint.right * 2 , armJoint.localRotation);
            a.Speed = power * 40;
            power = 0;
            animShot.ChangePic(0);
            if(powEffect != null)Destroy(powEffect.gameObject);
        }

        //各アニメーションの向きを設定
        animStop.transform.localScale = 
            animMove.transform.localScale = 
            animJump.transform.localScale =
            new Vector3((dire != 0 ? Mathf.Sign(dire) : animStop.transform.localScale.x), 1, 1);

        //移動
        rigid.velocity.x = dire;

        //アニメーションの表示非表示
        animStop.enabled = mode == Mode.Stop;
        animMove.gameObject.SetActive(mode == Mode.Walk);
        animJump.gameObject.SetActive(mode == Mode.Jump);
    }

    void AnimUpdate()
    {
        switch (mode)
        {
            case Mode.Walk:
                animMove.Updater();
                break;
        }
    }

    void RotateArm()
    {
        //マウスとプレイヤーの位置を算出
        Vector3 toDirec = 
            (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition) - (Vector2)armJoint.position;
        //マウスの方向に腕を回転
        armJoint.localRotation = Quaternion.FromToRotation(Vector3.right,toDirec);
        //マウスがプレイヤーより左にあるなら画をY反転
        armJoint.transform.localScale = new Vector3(1, Mathf.Sign(toDirec.x), 1);

    }
}

物理演算クラス

Rigider.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// 物理挙動クラス
/// </summary>
public class Rigider : MonoBehaviour
{
    [SerializeField,Tooltip("重力値をインスペクタから設定できるように")]
    float pyhs = -1f;
    [SerializeField,Tooltip("最大加速度")]float maxVelocity = 50;
    public Vector3 velocity;
    //地面に着いたかどうか
    public bool isGround { get { return transform.position.y <= 0; } }

    void Update()
    {
        //空中の時重力をかける
        if (velocity.y > 0 || transform.position.y != 0)
        {
            //最大加速度以下なら移動量加算
            if(Mathf.Abs(velocity.y) <= maxVelocity) 
                velocity.y += pyhs;

            if(transform.position.y < 0)
            {
                transform.position = new Vector3(transform.position.x, 0, 0);
                velocity.y = 0;
            }

        }

        //移動
        transform.position += velocity * Time.deltaTime;
    }

    public void AddForce(Vector3 alpha)
    {
        velocity += alpha;
    }
}

的クラス

Target.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 的クラス
/// </summary>
public class Target : Col
{
    [SerializeField] Parts effect = null;
    public int point { get; set; }
    Rigider rigid;
    Coroutine c;
    float jump;
    private void Start()
    {
        rigid = GetComponent<Rigider>();
        point = Random.Range(0, 10) + 1;

        //pintに比例して最低5最大30で跳ねる
        jump = point * 3;
        if (jump < 5) jump = 5;

        Manager.AddTargets(this);

        rigid.AddForce(Vector3.left * point / 2);
    }

    void Update()
    {
        //地面に着いたら跳ねる
        if (rigid.isGround) rigid.AddForce(new Vector3(0,jump));
        //一定距離離れたら削除
        if (Camera.main.transform.position.x - transform.position.x > 30)
        {
            if(c == null)c = StartCoroutine( RemoveList());
        }
    }

    IEnumerator RemoveList()
    {
        Manager.RemoveTargets(this);
        //Managerクラスでのエラー対策で1フレーム遅らせる
        yield return null; 
        Destroy(gameObject);
    }

    public override void OnHit()
    {
        //当たり判定削除
        Manager.HitTargets(this);
        //ランダム回転
        transform.GetChild(0).Rotate(0,0,Random.Range(0, 360));
        //破壊アニメーション
        StartCoroutine(DestroyCoroutine());
        //破壊パーティクル
        Parts p = Instantiate(effect, transform.position, transform.rotation,transform);
        p.particleSpeed = point;
    }

}

破壊アニメーションシェーダ

EffectsShader.Shader
//シェーダプログラミング(Unity独自シェーダ:ShaderLab)
//このプログラムをMaterialに貼り付ける
//参考資料URL
//http://nn-hokuson.hatenablog.com/entry/2017/04/14/204822
//http://tsumikiseisaku.com/blog/shader-tutorial-001/

Shader "Custom/EffectShader" {
    Properties {
        _Color ("色", Color) = (1,1,1,1)
        _MainTex ("元画像 (RGB)", 2D) = "white" {}
        _DisolveTex ("反映画像 (RGB)", 2D) = "white" {}
        _Threshold("しきい値", Range(0,1))= 0.0
    }
    SubShader {
        Tags {
            "Queue" = "Transparent"
            "RenderType" = "Transparent"
        }
        LOD 200 //描画タイミング
        CGPROGRAM //描画処理ここから

        //#pragma surface 関数名 ライティングモデル オプション
        #pragma surface surf Standard fullforwardshadows
        //使用バージョン(デフォルトは3)
        #pragma target 3.0

        sampler2D _MainTex;//表示画像
        sampler2D _DisolveTex;//エフェクト画像

        //後で使われるInputの構造体を宣言
        struct Input {
            float2 uv_MainTex;
        };
        half _Threshold; //しきい値
        fixed4 _Color; //fixe ×4→Vector4

        //struct SurfaceOutputStandard {
        //  fixed3 Albedo;      // 色(RGB) デフォルトは黒
        //  fixed3 Normal;      // 法線(XYZ) デフォルトは設定なし
        //  half3  Emission;    // 自己発光(RGB) デフォルトは黒
        //  half   Metallic;    // 金属かどうか(0 ~ 1) デフォルトは0
        //  half   Smoothness;  // ツルツル度合い(0 ~ 1) デフォルトは0
        //  half   Occlusion;   // オクルージョン・遮蔽(0 ~ 1) デフォルトは1
        //  fixed  Alpha;       // 不透明度(0 ~ 1) デフォルトは0
        //};

        void surf (Input IN, inout SurfaceOutputStandard o) {
            //uv_MainTexに_DisolveTexをかけてmに代入
            fixed4 m = tex2D (_DisolveTex, IN.uv_MainTex);

            half g = m.r * 0.2 + m.g * 0.7 + m.b * 0.1;
            if( g < _Threshold ){ //彩度がしきい値未満なら
                discard;//計算を破棄
            } 
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;//色を取得
            o.Albedo = c.rgb; //出力色に代入
            o.Emission = c.rgb;//発光(これがないと暗い)
            o.Alpha = c.a;//出力色に代入
        }
        ENDCG //描画処理終わり
    }
    //滑り止め(描画処理が対応できなかった時に行うシェーダ)
    FallBack "Diffuse"
}

多いし長いし
合計12個のプログラムになりました
印刷した時にホチキスの針が貫通しきらなくて3回ホチキス重ねした後に追いホチキスしたのはいい思い出です
image.png

HierarchyとInspector

ゲームに使用したGameObjectのそれぞれのヒエラルキーとインスペクタのスクショを載せていきます
GameObjectに必要なクラスと数値は確認できるはず
紹介はヒエラルキー→インスペクタの順番でスクショを載せていきます

シーン内ヒエラルキー

まずはシーン全体
image.png

GroundParticle

備考備考
setActive(false)なので見えません
画像は茶色の丸いやつです(土ぼこり用の画像)
image.pngimage.png

ArrowParticle

備考
Objに↑のGroundParticleのプレハブを入れてください
土ぼこりを出すパーティクルシステムです
image.pngimage.png

Arrow

備考
↑のArrowParticleのプレハブをIsGroundEffectに入れてください
このArrowがPlayerが放つ矢になります
image.pngimage.png

Ya

image.pngimage.png

KiraKira

備考
Playerが弓を引き切った時に出るパーティクルの粒子
image.pngimage.png

PlayerMaxPowerEffect

備考
Playerが弓を引き切った時に出るパーティクルの粒子
を出すオブジェクト
image.pngimage.png

Player

備考
各インスペクタのオブジェクトは、入ってるオブジェクトの名前で判断してください
(ArrowとMaxPowEffectはプレハブであとは子オブジェクト)
CameraTargetは空のオブジェクトなので省略
image.pngimage.png

Body

image.pngimage.png

Foot

image.pngimage.png

Jump

image.pngimage.png

Stop

image.pngimage.png

ArmAndBow

image.pngimage.png

Arm

備考
ズギャァァァァァァンって11枚ほど使います
image.pngimage.png

Canvas

備考
キャンバスは特に触ってなかったと思う(そもそもあまり関係ないし)
子オブジェクトの「Menu」「Game」は空のオブジェクトなので省略で
image.pngimage.png

Image(名前変えろよ)

備考
なんだ ただのタイトル画像か
image.pngimage.png

StartButton

image.pngimage.png

ScoreText

備考Directorから参照されます
image.pngimage.png

TimerText

備考Directorから参照されます
image.pngimage.png

Button(名前変えろよ)

備考Directorから参照されます
image.pngimage.png

TargetTip

備考
TargetParticleから参照されます
image.pngimage.png

TargetParticle

備考
Targetから参照されます
image.pngimage.png

Material

備考
的(まと)が破壊されるときのアニメーションのシェーダ
Targetから参照されます
↓スクリプトに紛れてたこいつ
image.pngimage.pngimage.png

Target

image.pngimage.png

Target

備考
作成したシェーダを搭載した?Materialを付与します
image.pngimage.png

Director

備考
ScoreText,TimeText,ButtonはCanvasのあれです
Directorは自身を指します
image.png
image.pngimage.png

Main Camera

備考
CameraTargetはPlayerの子オブジェクトです
image.pngimage.png

Manager

備考
DirectorはDirectorです
image.pngimage.png

Backgrounds

備考
背景をまとめる空オブジェクトです
image.pngimage.png

背景まとめる親オブジェクトの位置

各子オブジェクト Y座標
Grounds -2.5
Moutains 7.5
Trees0 5
Trees1 5
Trees2 5

各背景のX座標(すべて共通)

背景「○○」の時 X座標
○○ 0
○○(1) 20
○○(2) 40
○○(3) 60

例)○○がGroundならこう↓
image.png
image.png
image.pngimage.png
image.png
こんな感じで他のオブジェクトも設置してください
(画像が重ならない位置ってだけです)

OrderInLayerとratio

備考
すべての背景オブジェクトはSpriteRendererとBackgrounderが入っています
BackgrounderのTransDistは全部共通の「80」です(同じサイズで作ったから)
SpriteRendererのOrderInLayer と Backgrounderのratio使用画像がそれぞれ違います
image.png

背景名 OrderInLayer ratio 使用画像
Ground -10 0 Ground
Tree0 -70 0 Tree0
Tree1 -80 0.2 Tree1
Tree2 -90 0.5 Tree2
BackGroundMontain -100 0.8 BackGroundMontain

もう1回一覧
image.png

使用画像

画像の使用について

全部筆者が描いた絵なので、使用する時はこの記事のリンク貼ってくだされば加工なりなんなりと

なぜGitHubを使わないか

使い方がわからなんだ
わかったらリンク張っときます

一覧

image.png

Arm

Arm0.png

Arm0.png

Arm1.png

Arm1.png

Arm2.png

Arm2.png

Arm3.png

Arm3.png

Arm4.png

Arm4.png

Arm5.png

Arm5.png

Arm6.png

Arm6.png

Arm7.png

Arm7.png

Arm8.png

Arm8.png

Arm9.png

Arm9.png

Arm10.png

Arm10.png

BackButtonOrange.png

BackButtonOrange.png

BackGroundMontain.png

BackGroundMontain.png

Body.png

Body.png

Bow.png

Bow.png

Broken.png

Broken.png

Ground.png

Ground.png

GroundParticle.png

GroundParticle.png

JumpFall.png

JumpFall.png

JumpUp.png

JumpUp.png

Kirakira

Kirakira.png

Move0.png

Move0.png

Move

Move1.png

Move1.png

Move2.png

Move2.png

Move3.png

Move3.png

Move4.png

Move4.png

StartButton.png

StartButton.png

Stop.png

Stop.png

Target.png

Target.png

TargetTip.png

TargetTip.png

Title.png

ん?
Title.png

Tree

Tree0.png

Tree0.png

Tree1.png

Tree1.png

Tree2.png

Tree2.png

Ya.png

Ya.png

ホームページ制作初心者が、「とりあえず画像の貼り方覚えたから使ってみた」感がある記事になったな

さいごに

Processingでやろうと思えばやれるんじゃないですかね
(回転の仕様が違うからなんともですが)
そもそもプログラミングの書き方がUnity的だわ
やっと寝れる

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2