物體移動控制

要求

1斋射、物體移動主要因素:速度育勺、方向;
2绩鸣、移動的范圍不能超出屏幕邊界,當(dāng)碰觸到屏幕左右邊界時呀闻,應(yīng)更換方向化借;
3、可開啟追蹤模式捡多,如果與Player在一定距離內(nèi)蓖康,則追蹤Player,否則垒手,正常運行蒜焊;
4、應(yīng)增加一定隨機性科贬,增加運動的趣味性泳梆;

知識點

環(huán)境:
2D游戲;
物體通過Rigidbody2d來控制鳖悠;
Rigidbody2d設(shè)置BodyType屬性為Kinematic(不受重力等影響,可通過velocity來控制其運動)

1优妙、Rigidbody2d.velocity分析

1乘综、velocity可表示物體的速度和方向性
2、數(shù)值越大套硼,表示速度越快
3卡辰、坐標(biāo)系上、右為正方向邪意,數(shù)值應(yīng)為正數(shù)
4九妈、坐標(biāo)系左、下為負(fù)方向雾鬼,數(shù)值應(yīng)為負(fù)數(shù)

2萌朱、運動AI分析

1、碰撞屏幕邊界自動轉(zhuǎn)向能力:y方向不變呆贿,數(shù)值可波動嚷兔;x方向改變,數(shù)值可波動做入;
2冒晰、自動追蹤能力:距離限定
3、波動性:隨機系數(shù)

3竟块、追蹤分析

1壶运、一個正常運動的物體如何朝向另外一個物體運動,且速率基本不變浪秘?
2蒋情、計算兩物體向量差值,取其normalized耸携,指定給rigidbody.velocity屬性即可實現(xiàn)追蹤能力

Vector2 vDistance = target.transform.position - transform.position;
rigidbody.velocity = vDistance.normalized;

代碼實現(xiàn)

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

public class EnemyMove : MonoBehaviour {
    //velocity可表示物體的速度和方向性
    //數(shù)值越大棵癣,表示速度越快
    //坐標(biāo)系上、右為正方向夺衍,數(shù)值應(yīng)為正數(shù)
    //坐標(biāo)系左狈谊、下為負(fù)方向,數(shù)值應(yīng)為負(fù)數(shù)

    //運動AI:
    //1沟沙、碰撞屏幕邊界自動轉(zhuǎn)向能力:y方向不變河劝,數(shù)值可波動;x方向改變矛紫,數(shù)值可波動赎瞎;
    //2、自動追蹤能力:距離限定
    //3颊咬、波動性:隨機系數(shù)

    public float velocity_x = 0f;//x方向速度
    public float velocity_y = 0f;//y方向速度
    public float fluctuate = 0f;//速度波動范圍

    public bool doFollow = false;//追蹤务甥?
    public float doFollowDistance = 2f;//觸發(fā)追蹤的有效距離

    private bool isFollowing = false;//是否正在追蹤
    private Rigidbody2D rigidbody;//2D剛體組件

    /// <summary>
    /// 初始化運動參數(shù)
    /// </summary>
    /// <param name="velocity_x">x方向速度</param>
    /// <param name="velocity_y">y方向速度</param>
    /// <param name="fluctuate">速度波動范圍</param>
    public void reInit(float velocity_x, float velocity_y, float fluctuate){
        this.velocity_x = velocity_x;
        this.velocity_y = velocity_y;
        this.fluctuate = fluctuate;
    }

    /// <summary>
    /// 設(shè)置追蹤參數(shù)
    /// </summary>
    /// <param name="doFollow">是否開啟追蹤模式</param>
    /// <param name="doFollowDistance">觸發(fā)追蹤的有效距離</param>
    public void setDoFollow(bool doFollow, float doFollowDistance){
        this.doFollow = doFollow;
        this.doFollowDistance = doFollowDistance;
    }

    void Awake() {
        rigidbody = GetComponent<Rigidbody2D> ();
    }


    void Update () {
        if(rigidbody == null){
            return;
        }

        //如果開啟了追蹤模式牡辽,則執(zhí)行自動追蹤能力AI
        if(doFollow){
            moveFollow ();
        }

        //碰撞屏幕邊界自動轉(zhuǎn)向能力,同時波動速度大小
        moveRotation ();
        //移動
        move ();
    }

    /// <summary>
    /// 移動
    /// </summary>
    void move(){
        //如果沒有在追蹤敞临,則按照正常速度運行
        if(!isFollowing){
            rigidbody.velocity = new Vector2 (velocity_x, velocity_y);
        }
    }

    /// <summary>
    /// 碰撞屏幕邊界自動轉(zhuǎn)向能力催享,同時波動速度大小
    /// </summary>
    private void moveRotation(){
        //檢測是否與屏幕邊界碰撞,如果是哟绊,則改變方向
        if (AppCommon.isWidthBoundary (transform, velocity_x)) {
            //僅x方向改變即可
            velocity_x = -velocity_x;
            //根據(jù)波動范圍,波動速度的數(shù)值痰憎,使其效果更隨機票髓,AI更靈活智能
            velocity_x = doFluctuate (velocity_x);
            velocity_y = doFluctuate (velocity_y);
        }
    }

    /// <summary>
    /// 追蹤模式
    /// </summary>
    private void moveFollow(){
        //如果設(shè)定的距離為0,則不追蹤
        if(doFollowDistance == 0){
            return;
        }
        //獲得追蹤目標(biāo)對象铣耘,即Player
        GameObject target = GameObject.FindGameObjectWithTag ("Player");
        if(target == null){
            return;
        }
        //獲得與目標(biāo)對象的距離洽沟,如果在觸發(fā)追蹤的有效距離內(nèi),則開始追蹤Player
        float distance = Vector2.Distance (target.transform.position, transform.position);
        if(distance > doFollowDistance){
            isFollowing = false;
            return;
        }
        isFollowing = true;
        //計算兩物體向量差值蜗细,取其normalized裆操,指定給rigidbody.velocity屬性即可實現(xiàn)追蹤能力
        Vector2 vDistance = target.transform.position - transform.position;
        rigidbody.velocity = vDistance.normalized;
    }

    /// <summary>
    /// 波動數(shù)據(jù)
    /// </summary>
    /// <returns>波動后的值</returns>
    /// <param name="value">需要波動的值</param>
    private float doFluctuate(float value){
        if (fluctuate != 0) {
            float fluctuateAbs = Mathf.Abs (fluctuate);
            float fluctuateRandom =  Random.Range (-fluctuateAbs, fluctuateAbs);
            value += fluctuateRandom;
        }
        return value;
    }
}

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

public class AppCommon : MonoBehaviour {

    public static float app_velocity = 1f;

    private static float width;
    private static float height;
    private static float left;
    private static float right;
    private static float top;
    private static float bottom;

    void Start ()
    {
        Camera cam = Camera.main;
        height = 2f * cam.orthographicSize;
        width = height * cam.aspect;

        left = -width / 2;
        right = width / 2;
        top = height / 2;
        bottom = -height / 2;
    }

    /// <summary>
    /// Ises the width boundary.
    /// </summary>
    /// <returns><c>true</c>, if width boundary was ised, <c>false</c> otherwise.</returns>
    /// <param name="transform">Transform.</param>
    /// <param name="h">The height.</param>
    public static bool isWidthBoundary (Transform transform, float h)
    {
        //在left與right之間,返回false
        //在left左邊炉媒,手勢為正方向踪区,返回false
        //在right右邊,手勢為反方向吊骤,返回false
        if (transform.position.x > left && transform.position.x < right) {
            return false;
        }
        if (transform.position.x < left && h > 0) {
            return false;
        }
        if (transform.position.x > right && h < 0) {
            return false;
        }
        return true;
    }

    /// <summary>
    /// Ises the height boundary.
    /// </summary>
    /// <returns><c>true</c>, if height boundary was ised, <c>false</c> otherwise.</returns>
    /// <param name="transform">Transform.</param>
    /// <param name="v">V.</param>
    public static bool isHeightBoundary (Transform transform,float v)
    {
        //在top與right之間缎岗,返回false
        //在top上邊,手勢為正方向白粉,返回false
        //在bottom下邊传泊,手勢為反方向,返回false
        if (transform.position.y > bottom && transform.position.y < top) {
            return false;
        }
        if (transform.position.y > top && v < 0) {
            return false;
        }
        if (transform.position.y < bottom && v > 0) {
            return false;
        }
        return true;
    }
}

效果

3.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸭巴,一起剝皮案震驚了整個濱河市眷细,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鹃祖,老刑警劉巖溪椎,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異惯豆,居然都是意外死亡池磁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門楷兽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來地熄,“玉大人,你說我怎么就攤上這事芯杀《丝迹” “怎么了雅潭?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長却特。 經(jīng)常有香客問我扶供,道長,這世上最難降的妖魔是什么裂明? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任椿浓,我火速辦了婚禮,結(jié)果婚禮上闽晦,老公的妹妹穿的比我還像新娘扳碍。我一直安慰自己,他們只是感情好仙蛉,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布笋敞。 她就那樣靜靜地躺著,像睡著了一般荠瘪。 火紅的嫁衣襯著肌膚如雪夯巷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天哀墓,我揣著相機與錄音趁餐,去河邊找鬼。 笑死篮绰,一個胖子當(dāng)著我的面吹牛澎怒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阶牍,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼喷面,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了走孽?” 一聲冷哼從身側(cè)響起惧辈,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎磕瓷,沒想到半個月后盒齿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡困食,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年边翁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硕盹。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡符匾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘩例,到底是詐尸還是另有隱情啊胶,我是刑警寧澤甸各,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站焰坪,受9級特大地震影響趣倾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜某饰,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一儒恋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧黔漂,春花似錦碧浊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽比勉。三九已至劳较,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間浩聋,已是汗流浹背观蜗。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衣洁,地道東北人墓捻。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像坊夫,于是被迫代替她去往敵國和親砖第。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容