よく2Dゲームで見られる放物線に基づくの遊び方。

www.bilibili.com


1.先ず、Unity Hubを起動して、新しい2Dプロジェクトを新規作成してください。<2019.4.22f1使ってるけど、最新のバージョンをインストールして使ってください

2.地面を作る

Hierarchy内に2D objectSpriteSquareを作成して、座標Resetして、名前DragPointにする名前はGroundにする、それからInspectorでLayerを一つ追加して、名前もGroundにして選択してください。colorsizeは適当にしておいて。Ground選択して、Rigidbody2DBOXCollider2Dを追加して、Rigidbody2DBady TypeStaticに、以上したら地面の準備完了。

3.軌跡線現すためのGameObjectを作ります

空オブジェクトを作成して、座標Resetして、名前はLine1にして、InspectorLine Rendererを追加してください。ProjectNew Materialを作って、選択した状態でInspectorでのShaderのタイプはGUIにして、素材line-untiyのテクスチャをFont Textureにアタッチして、Tilingxを和4にする。効果は以下の図を見てください。

そしてLine1を選択し、Line RendererのPositionsでのSizeXの二行目を5にして、Texture ModeTileにして、Widthを0.1にすれば良いと思います。先ほど作ってたNew MaterialLine RendererMaterialsにアタッチしてcolorクリックして右上の矢印ボタンを選択してAlphaを0にする、Additional SettingsOrder in Layerを1にしてOKです。

4.力加減線を現すGameObject

空オブジェクトを作成して、座標Reset、名前はLine2にして、InspectorでLine Rendererを追加してください。PositionsでのSizeXの二行目を-1.5ぐらいにして、Widthを0.05にする、MaterialsDefault-Lineにして、Order in Layerを1に、ほぼLine1と同じ操作です。

5.球を作ります

空オブジェクトを作成して、座標Resetして、名前Ballにする、素材バスケットボールをInspectorでのSpriteにアタッチする、sizeを適用に調整して、Additional SettingsOrder in Layerを2に、Rigidbody2DCircle Collider2Dを追加して、ProjectにCreate>2D>Physics Material2Dを作成して、Bouncinessを0.3にする、それをBallCircle Collider2DMaterialにアタッチして、Rigidbody2DGravity Scaleを0に、Collision DetectionContinuousにする。

6.引っ張れる点

Hierarchy内に2D object SpriteCircleを作成して、座標Resetして、名前DragPointにする、Sizeは適当に、Additional SettingsOrder in Layerを1に、これで終わり、

7.コード

Parabola CTRLScriptBallにアタッチして、Line1Line1GameObjectを入れて、Line2も同様、Line1Numをに20、Max Forceに2、Release Forceに6、GroundGroundアタッチして、GroundLayerGroundに選択して、DragPointに先作ったのを入れて。実行してください。

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.EventSystems;

public class parabolaCTRL : MonoBehaviour
{
    private Vector2 mouse_Pos;  //マウス位置の世界座標

    public LineRenderer line1;  //軌跡線
    public int line1Num = 10;   //Line Renderの線分の数
    Vector3 points1;          //軌跡の配列値

    public LineRenderer line2;  //力加減線
    public float maxForce = 2;  //最大力加減
    int line2Num = 2;           //Line Renderの線分の数
    Vector3 points2;          //力加減の配列値

    Rigidbody2D rb2D;           //球のRigidbody2D
    public float releaseForce;  //限外の力

    Vector2 release_Velocity;   //初速度
    float S;                    //最大の水平距離
    float t;                    //水平飛ぶ時間
    float g = 9.8f;             //重力加速度
    public Transform ground;    //地面
    float height;               //地面から球までの高さ
    float xUnit = .1f;          //X軸の描く間隔

    //地面Layer
    public LayerMask groundLayer;

    //引っ張れる点
    public GameObject dragPoint;

    //軌跡線の始点の色
    Vector4 fadeLine = new Vector4(1,1,1,1);


    enum STATE
    {
        NONE = -1,

        IDLE = 0,   //静止
        GRAB,       //触る
        DRAG,       //引っ張る
        RELEASE,    //手離す
        LAND,       //着地

        NUM,
    }

    private STATE state = STATE.IDLE;       //最初の状態
    private STATE next_state = STATE.NONE;  //次の状態

    private void Start()
    {
        //Line Renderの線分の数を設定する<Unity API
        line1.positionCount = line1Num;
        line2.positionCount = line2Num;

        //線分の数によって、配列値を決める
        points1 = new Vector3[line1Num];
        points2 = new Vector3[line2Num];

        //Rigidbody2D
        rb2D = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        //マウス位置の世界座標を読み込み
        mouse_Pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

        //-------------------状態変更---------------------------------------
        switch (state)
        {
            //手離すの状態下で,地面に検測したら,着地の状態に変更。
            case STATE.RELEASE:
                if (rb2D.IsTouchingLayers(groundLayer) && rb2D.velocity.y == 0)
                    next_state = STATE.LAND;
                break;

            //着地の状態で,もし球が静止になったら,静止状態に変更
            case STATE.LAND:
                if (rb2D.velocity == Vector2.zero)
                    next_state = STATE.IDLE;
                break;
        }


        //---------------------状態初期化------------------------------------------
        //状態変更する場合、一回だけ行い
        if (next_state != STATE.NONE)
        {
            //状態変更
            state = next_state;
            next_state = STATE.NONE;


            switch (state)
            {
                //触る時に
                case STATE.GRAB:

                    rb2D.gravityScale = 0;                              //重力影響を0に
                    height = transform.position.y - ground.position.y;  //地面から球までの高さを取り
                    
                    line1.startColor = new Vector4(1, 1, 1, 1);         //改めて軌跡線を現す
                    line2.enabled = true;
                    dragPoint.SetActive(true);
                    
                    next_state = STATE.DRAG;          //引っ張る状態に入りの準備をする
                    break;

                //手離す時に
                case STATE.RELEASE:

                    //球のRigidbody2Dのプロパティの調整
                    rb2D.drag = 0;                  //抗力
                    rb2D.gravityScale = 1 ;         //重力
                    rb2D.velocity = release_Velocity;//初速度

                    line2.enabled = false;          //力加減線を隠す
                    dragPoint.SetActive(false);
                    break;

                //着地状態に入る時
                case STATE.LAND:

                    //球を止めるため、抗力を少しアップします
                    rb2D.drag = 0.8f;
                    break;

            }
        }

        //------------------------状態の行い-------------------------------------
        switch (state)
        {
            case STATE.DRAG:

                //###引っ張る時に線分を現す###
                
                //マウスと球の位置を繋ぐ線分
                points2[0] = transform.position;
                points2[1] = mouse_Pos;

                //もし最長を超えたら,最長になる
                if (Vector3.Distance(points2[0], points2[1]) > maxForce)
                {
                    points2[1] = points2[0] + (points2[1] - points2[0]).normalized * maxForce;
                }
                line2.SetPositions(points2);

                //末端にある引っ張れる点の位置
                dragPoint.transform.position = points2[1];

                //###軌跡放物線###
                //初速度
                release_Velocity = (points2[0] - points2[1]) * releaseForce;

                //着地から最大水平移動距離
                S = release_Velocity.x * (release_Velocity.y / g + Mathf.Sqrt*1;

                //水平移動によって、軌跡のX軸の描く間隔を確認する
                xUnit = S / line1Num;

                //LineRenderを結合して画像を描く
                for (int i = 0; i < line1Num; i++)
                {
                    points1[i].x = transform.position.x + i * xUnit;
                    points1[i].y = GetFuncPathY(points1[i].x);
                }
                line1.SetPositions(points1);

                break;

            case STATE.RELEASE:
                //軌跡線が徐々に消える
                fadeLine.w -= Time.deltaTime * 2;
                Mathf.Clamp01(fadeLine.w);
                line1.startColor = fadeLine;
                break;
        }
    }

    //マウス押すと,触る状態になる
    private void OnMouseDown()
    {
        next_state = STATE.GRAB;
    }

    //でないと,手離す状態になる
    private void OnMouseUp()
    {
        next_state = STATE.RELEASE;
    }

    //Y座標関数を取る。>放物線の軌跡方程式<
    float GetFuncPathY(float x)
    {
        float y;
        y = (release_Velocity.y / release_Velocity.x) * (x - transform.position.x) - (g * (x - transform.position.x) * (x - transform.position.x)) / (2 * release_Velocity.x * release_Velocity.x) + transform.position.y;
        return y;
    }
}

以上です。

 

素材やコードなどまとめています

<下手ですが、コードの注釈を日本語に翻訳しました>

drive.google.com
ビリビリ動画から運んできました。自分のものではありません。もし権利侵害したら、連絡してください、削除します。www.bilibili.com

 

 

 

 

 

*1:release_Velocity.y * release_Velocity.y / g / g) + 2 * height / g

Unityでダメージを受けたキャラのHPバーの作り方を紹介します!

www.bilibili.com

1.先ずはUnity開いて、今回もは2Dオブジェクトで作成して名前はHealthBarにします。

2.開いたら、HierarchyCanvasを追加してから空オブジェクトを作って、座標Resetして、名前はHealthBarにします、右クリックして、UIimageをそのHealthBarの子供にして、名前はHealthにします。imageSourceImageに素材をアタッチして、ImageTypeFilledで、FillMethodHorizontalして、SetNativeSizeをクリック。

3.また、HealthBarの下でHealthと同じImageを作って、名前はBGにします。今回は素材SourceImageにアタッチしてから、直接SetNativeSizeをクリックしてください。

4.Healthをコピーして、名前はHealthFadeにします、Colorだけ不透明度を本来の半分にします。

5.GameManagerを作ります、座標Resetして、二つのコードをアタッチします。図のように:

画面をクリックすれば以下のような効果ができます!

コード以下:

HealthBarCTRL

using System.Collections;
using System.Collections.Generic;

using UnityEngine;
using UnityEngine.UI;

public class HealthBarCTRL : MonoBehaviour
{
    public Image health_image;
    public Image health_fade;

    private void Update()
    {
        health_image.fillAmount = HealthPointCTRL.health_point / 100f;
        health_fade.fillAmount = HealthPointCTRL.fade_health_point / 100f;
    }
}

HealthPointCTRL

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HealthPointCTRL : MonoBehaviour
{

    public static float health_point, fade_health_point;
    float fade_Timer = 0;
    public float fade_Time=1f;
    Coroutine damage_Coroutine = null;

    private void Awake()
    {
        health_point = 100f;
        fade_health_point = 100f;
    }

    private void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            fade_Timer = 0;
            Damage_Once(10);
        }
        else if(Input.GetMouseButtonDown(1))
        {
            if(damage_Coroutine!=null)
            {
                StopCoroutine(damage_Coroutine);
                damage_Coroutine = StartCoroutine(Damage_Over_Time(5, 2));
            }
            else
            {
                damage_Coroutine = StartCoroutine(Damage_Over_Time(5, 2));
            }
            fade_Timer += Time.deltaTime;

            if(fade_health_point>health_point&&fade_Timer>fade_Time)
            {
                fade_health_point = Mathf.Lerp(fade_health_point, health_point, Time.deltaTime * 2);
            }
        }
    }

    public void Damage_Once(float damage)
    {
        health_point -= damage;
    }

    public IEnumerator Damage_Over_Time(float damage, float duration)
    {
        float timer = 0;
        while(health_point>=0&&timer<=duration)
        {
            health_point -= damage * Time.deltaTime;
            timer += Time.deltaTime;
            yield return null;
        }
    }
}

 

ビリビリ動画から運んできました。自分のものではありません。もし権利侵害したら、連絡してください、削除します。