2017-02-13 09:50:47 lei_7103 阅读数 4031
1.第一步,首先新建一个unity3d项目,导入Standard Assets>ImageEffects 插件(灰屏效果有用到噢),格外还导入Demo用到的角色资源[Spider Green插件];

    

    2.第二步,需要在场景中创建一个摄像机,并且摄像机附加ColorCorrectionCurves.cs 组件;

    


    3.第三步,把Spider Green中的SPIDER.Prefab拖到场景中,并且新加组件GameOver.cs;

      

    GameOver.cs代码如下:

     
[C#] 
?
 
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.ImageEffects;
 
public class GameOver : MonoBehaviour {
 
        private  Animation _curAnim;
        private ColorCorrectionCurves _colorCor;
 
        // Use this for initialization
        void Start () {
                if (_curAnim == null)
                        _curAnim = GetComponent<Animation> ();
 
                if (_colorCor == null)
                        _colorCor = FindObjectOfType<ColorCorrectionCurves> ();
        }
 
        void OnGUI()
        {
                if (GUI.Button (new Rect (50, 100, 100, 50), "怪物重生")) {
                        SetAnimationPlay ("Attack",WrapMode.Loop);
                        SetColorCorrectionCurvesSaturation (1);
 
                }
                if (GUI.Button (new Rect (50, 200, 100, 50), "杀死怪物")) {
                        SetAnimationPlay ("Death",WrapMode.Once);
                        SetColorCorrectionCurvesSaturation (0);
                }
        }
        /// <summary>
        /// 设定当前播放的动画
        /// </summary>
        /// <param name="animName">Animation name.</param>
        /// <param name="wrapL">Wrap l.</param>
        void SetAnimationPlay(string animName,WrapMode wrapL)
        {
                if (_curAnim) {
                        _curAnim.Play (animName);
                        _curAnim.wrapMode = wrapL;
                }
        }
        /// <summary>
        /// 设定当前摄像机的颜色度
        /// </summary>
        /// <param name="duration">Duration.</param>
        void SetColorCorrectionCurvesSaturation(int duration)
        {
                if (_colorCor)
                        _colorCor.saturation = duration;
        }
}
m>
    void SetColorCorrectio

    4.最后,直接运行项目看效果啦!

       


       
2014-04-16 20:18:56 qinyuanpei 阅读数 8420

         大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei

         感谢对我的支持,在上一篇文章《 [Unity3D]Unity3D游戏开发之仿仙剑奇侠传角色控制效果》中,我们通过自定义脚本实现了在RPG游戏中的角色控制器,当然这个角色器目前还不完善,在碰撞以及控制等方面还存在某些问题和不足,对于这些问题,我会在后面的一篇文章中会给大家做详细的说明,力图设计出一个为RPG游戏服务的角色控制器,方便大家开发RPG类型的游戏。那么,今天我想和大家分享的是在Unity3D中一个比较重要的组件——布娃娃(Ragdoll)。我们首先来看张图片吧!

 

          相信熟悉仙剑的朋友一定知道这样一句话:胜败乃兵家常事,大侠请重新来过。从仙剑一到仙剑五前传,仙剑带给我们的感动里不仅仅是一个个跌宕起伏、感人至深的故事,还有每一次战斗失败之后从头再来的勇敢。人生有时候就像游戏一样,我们总会遇到这样或着那样的挫折和困难。虽然在仙剑这样一个五灵六界的世界观下,人类基本作为最弱小的生命存在,但是每次我们的主角们不是一直在努力去做吗?所以我们的人生一定要积极向上,充满激情地去做一件事情。博主最讨厌的就是玩游戏玩到最后只剩下打嘴仗的这种玩家,游戏一定是有输有赢的,试问各位仙剑玩家哪一个没有被Boss虐过,可是游戏的乐趣不就是在于一遍遍地去超越自己吗?输不可怕,怕的是我们因为输了就丧失了努力的勇气。我觉得仙剑一直再像我们传递一种正能量,那就是我们一定要让自己勇敢,人生中有很多的事情或许我们都无法掌控,就像李逍遥剑术超凡却不能帮助灵儿逃脱宿命、云天河拥有神龙之息、后羿射日神弓,为救山下百姓而箭射琼华,却救不了心爱的女孩儿的性命、夏侯瑾轩以为 凡事尽心尽力就能做好,可是到最后他却只能拿匕首刺向瑕妹子,只是为了不让枯木占据她的身体。或许我们并不知道未来会是什么样子吧,但是至少在此时此刻,我们曾经努力过、我们很用心地做过某些事情,这样就够了。好了,我们不去评论这些玩家了,我们正式开始今天的内容。

         在RPG游戏中,当角色HP降低到0时,角色即进入了死亡状态,此时角色将倒在地上。在过去的游戏设计中,角色倒在地上的动作通常是由动画师绘制一定的动画来完成的,这种方式虽然简单,但是由于角色倒地的动作都是相同的,无法实时反映出角色受攻击的情况,所以在游戏开发领域逐渐形成了一种新的模型即布娃娃(Ragdoll),该模型就是用来模拟角色死亡的状态的。在Unity3D中,系统为我们提供了布娃娃组件,下面请大家和我一起来学习怎样使用布娃娃来模拟角色死亡的状态吧:

         首先我们创建一个新项目,在场景中创建一个Plane和平行光,接下来我们导入我们事先准备好的FBX模型,此时在游戏场景中应该可以看到下面的内容:


       接下来,我们选中模型Samuzai,为其创建一个布娃娃组件:


          我们一起来看打开的对话框:


        如果我们的模型中提供了骨骼动画的话,那么我们单击右侧的选择按钮就能找到相应的文件,然后我们点Create,此时模型下的骨骼组件应该会变成下面这个样子:


      我们将盒子碰撞器移除,将模型的动画设为None,现在我们来运行程序:


      可以看到,我们的角色很真实地倒在了地上,而且如果我们多次运行程序的话,会发现角色每次死亡的时候都是不一样的,这样大大增强了游戏的真实感,如果每次战斗死亡的姿势都是一样的,这样会不会视觉疲劳呢?虽然《轩辕剑6》的市场反响并不怎么样,然而得益于Unity3D中的强大物理引擎,每次怪物死亡的时候都死得比较有范儿,大家可以自己去玩玩试玩版啊,哈哈。这里希望仙剑奇侠传的后续作品能够注意到这个问题,作为大侠,我们要死得轰轰烈烈的嘛,好了,这就是今天的文章了,希望大家喜欢!

     喜欢我的博客请记住我的名字:秦元培,我的博客地址是:blog.csdn.net/qinyuanpei

     转载请注明出处,本文作者:秦元培,本文出处:http://blog.csdn.net/qinyuanpei/article/details/23869275


2014-04-18 20:17:09 qinyuanpei 阅读数 6183

          大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei

         在前面的文章中,我们分别实现了一个自定义的角色控制器《[Unity3D]Unity3D游戏开发之仿仙剑奇侠传角色控制效果》和角色死亡的效果《[Unity3D]Unity3D游戏开发之仿仙剑奇侠传角色死亡效果实现》。今天我们继续来做点和仙剑相关的东西,首先我们来看一副图:


         这幅图呢,是仙剑奇侠传的第一个迷宫场景——仙灵岛的莲花池。男主角李逍遥为替婶婶求药独闯仙灵岛,在经历了前面的小草妖战斗后,李逍遥就来到了 莲花池,这个迷宫的解法很简单,乘坐莲花池中的芦苇垫到不同的地方,然后用破天锤打碎五座阿修罗像,通往仙灵岛的通路就会被打开,就是在仙灵岛李逍遥邂逅了正在沐浴的赵灵儿,仙剑奇侠传的故事从此展开。好了,故事先说到这里,我们来看这里很重要的一个信息:李逍遥踩着芦苇垫到达不同的地方,然后用破天锤打碎石像开启机关。我们把最终要的东西提取出来的话就是我们可以踩着芦苇垫子到不同的地方去。好,我们今天就来实现一个简化的"仙灵岛"吧!那么怎么做呢?不知道大家还记不记得我在《[Unity3D]Unity3D游戏开发之基于ITween实现寻路功能》这篇文章里提到过的寻路方法,在这篇文章中,我们最终实现的效果是这样的:


        现在呢,让我们把莲花池里的构件做一下抽象:每一个 石柱可以看做是一个寻路节点,芦苇垫子可以看做是绑定了寻路组件的一个GameObject。唯一的区别就在于这里的芦苇垫子是需要我们的角色站在上面才能让它运动的,而我们在这篇文章里的游戏体是自己运动的。好,现在我们开始来实现这个功能吧。我们先创建如下图所示的场景:


       我们在水中布置了8个石柱,两个芦苇垫子,当游戏开始时,玩家控制角色走上芦苇垫子时,芦苇垫子将按照事先设定的路线,将角色送达最后一个石柱位置,此时,玩家可以控制角色到达对岸。当玩家再次踏上芦苇垫子时,芦苇垫子会将角色送回起点位置。当芦苇垫子处于移动状态中时,角色可以向四个方向旋转,活动范围仅限于芦苇垫子上。好,交待清楚了场景,我们下面来讲解原理:

       1、角色控制

             采用在《[Unity3D]Unity3D游戏开发之仿仙剑奇侠传角色控制效果》中实现的角色控制器来控制角色的行为。

       2、寻路的实现

             采用在《[Unity3D]Unity3D游戏开发之基于ITween实现寻路功能》中实现的寻路组件作为基础脚本,本节在此基础上做扩充和完善,保证角色可以自由的移动

       基于以上两个原理,我们下面来编写今天的脚本:

using UnityEngine;
using System.Collections;

public class TransportScript : MonoBehaviour {
	
	//寻路组件节点
	public Transform[] mPaths;
	//芦苇垫传送器
	private Transform mTransportor;
	//被传送的角色
	public Transform mTransportPlayer;
	
	//起点
	Vector3 StartPoint=new Vector3(0F,0.5F,-13F);
	//终点
	Vector3 EndPoint=new Vector3(0F,0.5F,10F);
	
	//定义移动的方向类型:从起点到终点为0,从终点到起点为1
	private int MoveType=0;
	//定义移动状态的标志变量
	private bool isMoving=false;
	
	//存储寻路组件设置的哈希表
	private Hashtable args=new Hashtable();
	
	void Start () 
	{
		//获取传送器
		mTransportor=this.transform;

		//初始化寻路插件
	    Hashtable args = new Hashtable();
	    //设置路径的点
		args.Add("path",mPaths);
		//设置类型为线性,线性效果会好一些。
		args.Add("easeType", iTween.EaseType.linear);
		//设置寻路的速度
		args.Add("speed",2.5f);
	    //移动的整体时间。如果与speed共存那么优先speed
		args.Add("time",10f);
		//是否先从原始位置走到路径中第一个点的位置
		args.Add("movetopath",true);
		//延迟执行时间
		args.Add("delay", 0.1f);
		//移动的过程中面朝一个点
		args.Add("looktarget",Vector3.up);
		//三个循环类型 none loop pingPong (一般 循环 来回)	
		args.Add("loopType", "pingPong");
		//是否让模型始终面朝当面目标的方向
		//如果你发现你的模型在寻路的时候时钟都是一个方向那么一定要打开这个
		args.Add("orienttopath",true);
	
		iTween.MoveTo(gameObject,args);
		iTween.Pause();
	}
	
	void  Update()
	{
	   //如果当前处于停止状态则暂停动画
	   if(isMoving==false)
	   {
		  iTween.Pause();
	   }

	   //从起点到终点的控制
	   if(MoveType==0 && mTransportor.position!=EndPoint && isMoving==true)
	   {
		  //未到达终点则继续运动
	      mTransportPlayer.position=mTransportor.position;
	   }else if(MoveType==0 && mTransportor.position==EndPoint)
	   {
		  //到达终点则暂停运动
		  iTween.Pause();
		  isMoving=false;
		  MoveType=1;
	   }
		
	   //从终点到起点的控制
	   if(MoveType==1 && mTransportor.position!=StartPoint && isMoving==true)
	   {
		  //未到达终点则继续运动
	      mTransportPlayer.position=mTransportor.position;
	   }else if(MoveType==1 && mTransportor.position==StartPoint)
	   {
		  //到达终点则暂停运动
		  iTween.Pause();
	      isMoving=false;
		  MoveType=0;
	   }
	   
	}
	
	//当角色走上芦苇垫的时候开始移动动画
	void OnTriggerEnter(Collider mCollider)
	{
		if(mCollider.gameObject.name=="Samuzai")
		{
		   
		   if(isMoving==false)
		   {
			  isMoving=true;
	          iTween.Resume();
		   }
		}
    }
}

        在上面的代码中,我们需要把握以下几点:

        1、在Start()方法中,我们主要完成的是寻路组件的初始化,这里我们将寻路动画设置为来回,然后通过Pause()、Resume()方法两个方法来控制动画的播放,因为iTween没有提供在Update()中实现动画播放的方法,iTween只支持部分方法在Update()方法中使用,具体的大家可以自己去了解iTween的API文档。

        2、我们主要通过isMoving标志来标记当前的状态,使用OnTriggerEnter()方法来判断角色是否走上了芦苇垫子,当角色走上芦苇垫子上时,就开始播放寻路动画。当到达起点/终点时,寻路动画即停止。当角色再次走上芦苇垫子时,再次开始寻路动画。

       3、我们再Update()方法中通过改变角色的位置实现了角色和芦苇垫子的同步移动,当到达起点/终点时,寻路动画即停止,直到下一次被触发。

       4、触发与碰撞的区别在于触发不会产生力的作用,可以通过OnTriggerEnter/OnTriggerStay/OnTriggerExit方法分别监听触发开始、触发中、触发结束。要使用Trigger需要勾选碰撞器的isTrigger选项。具体的区别我会在后面的文章中为大家做讲解。

      

       这篇文章中用到的东西就是这么多,主要的难点是寻路动画的控制,由于官方没有提供有关的方法,所以我们只能采用Pause()、Resume()方法来控制角色的动画。最后我们来一起看看实现的效果吧,是不是有仙灵到的感觉呢?呵呵

      



      最后奉上几个民间的同人游戏演示:

      1、UDK制作的仙剑一3D版仙灵岛场景

      2、U3D制作的仙剑五前传同人演示1

            U3D制作的仙剑五前传同人演示2

      每次看到这里,内心都会充满一种希望,希望在有生之年玩到更多的仙剑,踏歌长行、梦想永续!继续努力吧!  

      喜欢我的博客请记住我的名字:秦元培,我的博客地址是:blog.csdn.net/qinyuanpei

      转载请注明出处,本文作者:秦元培,本文出处:http://blog.csdn.net/qinyuanpei/article/details/24038749


2018-10-22 13:50:04 o0xiaoyin0o 阅读数 1183

最近刚开始看unity3d游戏开发,感觉2d游戏似乎简单些,所以先从2d游戏入手试试看吧。

2d游戏大约要分为背景,角色(需要控制的己方角色car,敌机enemy,奖励物品prop),ui(分数显示,暂停继续等),音乐(背景音乐,攻击音乐,死亡音乐等)

大约长这样,emmm,原视频是主角是小飞机,背景是天空,也给有素材,但起初学习的时候想稍微更改下,就自己制作了小汽车主角和马路的背景,之后。。。觉得有点麻烦还是用了源素材,所以忽略这种突兀的感觉吧!

1.首先背景移动,需要两张背景交替向下移动,实现背景连续移动的效果。挂在背景图片上。

 

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

public class move : MonoBehaviour {        //背景移动

    public float speed = 2f;        //速度
    
    // Update is called once per frame
    void Update ()
    {
        this.transform.Translate (Vector3.down * speed * Time.deltaTime);        //每帧向下移动
        Vector3 postion = this.transform.position;
        if (postion.y <= -20.48f) {        //如果移动超过。。则向上移动,实现循环
            this .transform .position = new Vector3 (postion .x,postion .y + 20.48f*2,postion .z);
        }
    }
}

2.主角car(好吧假装是个飞机)实现发射子弹与主角的移动

创建两个空物体作为主角的子对象,放在子弹发射的起始位置,这样子弹就会相对主角的位置移动,只用实现子弹生成与移动就好了。为子弹添加2d碰撞检测器,当子弹碰到敌机时调用敌机的死亡脚本

子弹生成

public class gun : MonoBehaviour {

    public float rate = 0.1f;       //子弹生成时间间隔
    public float speed = 2f;        //子弹生成速度
    public GameObject bullet;
    // Use this for initialization


    public void fire ()
    {
        GameObject .Instantiate (bullet,transform .position ,Quaternion .identity );
    }
    public void openfire(){
        InvokeRepeating ("fire",1,rate);    //1秒后开始生成子弹,之后每隔rate个时间生成一个
    }
    public void stopfire ()
    {
        CancelInvoke ("fire");
    }

}

子弹移动

public class bullet : MonoBehaviour {    //子弹移动

    public float speed = 5f;


    void Update ()
    {
        transform.Translate (Vector3.up * speed * Time.deltaTime);
        if (transform.position.y >= 8.5f) {          //如果子弹移动出屏幕范围,销毁
            Destroy (this .gameObject );
        }
    }

    void OnTriggerEnter2D (Collider2D other)
    {
        if (other.tag == "enemy") {        //击中敌机,调用敌机的BeHit方法并将自身删除
            if (!other.GetComponent <enemy > ().isDeath) {
                other.gameObject.SendMessage ("BeHit");
                GameObject.Destroy (this.gameObject);
            }
        }
    }
}

将子弹生成脚本挂在空物体上,在Bullet后找到相应的子弹物体

将子弹移动脚本挂在子弹物体上

对于主角car,通过切换两张图片实现主角的动画(我记得sprite有个直接把2d序列帧图片放在一张图片上会自动裁切并且按序列帧播放的,但是没有尝试,之后再说吧),通过检测鼠标按下时的位置来对car进行移动(需要将屏幕坐标转换为世界坐标),判断car在世界坐标中的位置来控制car不移出背景。

public class car : MonoBehaviour
{

    public bool animation = true;
    //动画控制开关

    public int frameCountPersconds = 10;
    //每秒播放10帧

    public Camera TempC;

    public float timer = 0;
    //计时器

    public Sprite[] sprites;

    public float superGunTime = 10f;

    public gun gunRight;

    public gun gunLeft;

    private float resetSuperGunTime;

    private bool isMouseDown = false;

    private  Vector3 lastMoustPosition = Vector3.zero;

    //    private Transform hero;

    private int gunCount = 1;


    void Start ()
    {
//        spreteRender = this .GetComponent <SpriteRenderer >();
//        hero = GameObject .FindGameObjectWithTag ("hero").transform ;        //利用标签找物体
//        TempC  = this.GetComponent <Camera >();
        resetSuperGunTime = superGunTime;
        superGunTime = 0;
        gunLeft .openfire ();
    }

    void Update ()
    {
        if (animation) {        //切换两张图片实现动画
            timer += Time.deltaTime;        //计时
            int frameIndex = (int)(timer / (1f / frameCountPersconds));     //图片切换几次
            int frame = frameIndex % 2;     //将图片切换次数循环
            this.GetComponent <SpriteRenderer > ().sprite = sprites [frame];        //将图片于次数对应
        }
        if (Input.GetMouseButtonDown (0)) {        //检测鼠标是否按下
            isMouseDown = true;
        }
        if (Input.GetMouseButtonUp (0)) {
            isMouseDown = false;
//            lastMoustPosition = Vector3 .zero ;
        }
        if (isMouseDown && scoreShow .instance .gameState == GameState.Runing ) {    //鼠标按下且游戏是运行状态(非暂停)
            if (lastMoustPosition != Vector3.zero) {
        
                //    Camera .main .ScreenToWorldPoint (Input .mousePosition )    将屏幕坐标转化为世界坐标
//                Debug .Log ("Camera.main.ScreenToWorldPoint(Input .mousePosition"+TempC .ScreenToWorldPoint(new Vector3 ( //Input .mousePosition.x,Input .mousePosition .y,10.0f )));
                Vector3 offset = TempC.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, 10f)) - lastMoustPosition;        //坐标不能为0
                transform.position = transform.position + offset;        //移动
                checkPosition ();
            }
            lastMoustPosition = TempC.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, 10f));
        }
        superGunTime -= Time.deltaTime;
        if (superGunTime > 0) {     //切换超级子弹
            if (gunCount == 1) {
                transformToSuperGun ();
            }
        } else {
            if (gunCount == 2) {
                transformToNormalGun ();
            }
        }        
    }

    private void transformToSuperGun ()
    {
        gunCount = 2;
        gunRight.openfire ();
        gunLeft.stopfire ();

    }

    private void transformToNormalGun ()
    {
        gunCount = 1;
        gunRight.stopfire ();
        gunLeft.openfire ();

    }

    private void checkPosition ()           //检测car移动的位置防止移动出背景
    {
        //check -2.1<x<2.1
        //check -3.23<y<2.84
        Vector3 pos = transform.position;
        float x = pos.x;
        float y = pos.y;
        if (x < -2.1f) {
            x = -2.1f;
        }
        if (x > 2.1f) {
            x = 2.1f;
        }
        if (y < -3.23f) {
            y = -3.23f;
        }
        if (y > 2.84f) {
            y = 2.84f;
        }
        transform.position = new Vector3 (x, y, 0);
        
    }

    public void OnTriggerEnter2D (Collider2D collider)      //如果碰撞到标签是prop的物体,切换超级子弹(初始化superGunTime,并逐渐减少)
    {    
        if (collider.tag == "prop") {
            prop prop = collider.GetComponent <prop > ();
            if (prop.type == 0) {
                superGunTime = resetSuperGunTime;
                Destroy (collider .gameObject );
            }
        }
    }
}

  3.敌机与奖励物品生成和移动

创建空物体,放在屏幕外稍微靠上的部位用于敌机和奖励物品的生成。利用随机数控制敌机生成的位置

public class spawn : MonoBehaviour {        //敌机和奖励的生成

    public GameObject enemy0;
    public GameObject enemy1;
    public GameObject enemy2;

    public GameObject prop0;
    public GameObject prop1;

    public float rate0 = 1f;
    public float rate1 = 5f;
    public float rate2 = 8f;

    public float rateProp0 = 3f;
    public float rateprop1 = 5f;

    // Use this for initialization
    void Start () {
        InvokeRepeating ("createnemy0",1,rate0);
        InvokeRepeating ("createnemy1",3,rate1);
        InvokeRepeating ("createnemy2",5,rate2);

        InvokeRepeating ("creatprop0",5,rateProp0);
        InvokeRepeating ("creatprop1",8,rateprop1);
    }
    
    // Update is called once per frame
    void Update ()
    {
    }
    
    public void createnemy0(){
        float x0 = Random .Range (-2.3f,2.3f);
        GameObject .Instantiate (enemy0  ,new Vector3 (x0,this .transform .position .y,0),Quaternion .identity );
        }
    public void createnemy1(){
        float x1 = Random .Range (-2.2f,2.2f);
        GameObject .Instantiate (enemy1  ,new Vector3 (x1,this .transform .position .y,0),Quaternion .identity );
        }
    public void createnemy2(){
        float x2 = Random .Range (-1.8f,1.8f);
        GameObject .Instantiate (enemy2  ,new Vector3 (x2,this .transform .position .y,0),Quaternion .identity );
        }

    public void creatprop0(){
        float x0 = Random .Range (-2.2f,2.2f);
        GameObject .Instantiate (prop0  ,new Vector3 (x0,this .transform .position .y,0),Quaternion .identity );
        }
    public void creatprop1(){
        float x1 = Random .Range (-2.1f,2.1f);
        GameObject .Instantiate (prop1  ,new Vector3 (x1,this .transform .position .y,0),Quaternion .identity );
        }
}

奖励物品比较简单,只用移动,检测到于主角car碰撞后将自身删除就可以了

public class prop : MonoBehaviour {        //奖励物品移动

    public float speed = 1.5f ;
    public GameObject award;
    public int type = 1;
    public float posY;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        this .transform .Translate (Vector3 .down *speed *Time .deltaTime );
        if (this .transform .position .y <= posY ){
            Destroy (this.gameObject );
        }
    }
}

敌机的状态较为复杂,三种敌机分别设置不同的移动速度,有不同的hp值和分数,当子弹碰撞到敌机时切换敌机状态为BeHit状态,hp递减且播放受伤动画(不知道为什么这里的受伤动画一直没弄好)当hp为0时切换为toDie,调用isDeath方法并且增加分数。isDeath为true时播放死亡动画,动画播放完后删除此物体

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

public enum EnumyType{
        smallEnemy,
        middleEnemy,
        bigEnemy
}

public class enemy : MonoBehaviour {        

    public int hp = 1;
    public float speed = 2f;

    public int score = 100;

    public float posY;

    public EnumyType type =  EnumyType.smallEnemy ;

    public bool isDeath = false ;

    public Sprite [] explosionSprites;
    private float timer = 0;
    public int frameCountPersconds = 20;

    private  SpriteRenderer render;

    public float hitTimer = 0.2f;
    private float resetHitTime;
    public Sprite [] hitSprites;
    // Use this for initialization
    void Start () {
        render = this.GetComponent <SpriteRenderer>();

        resetHitTime  = hitTimer ;
        hitTimer = 0f;
    }
    
    // Update is called once per frame
    void Update ()
    {        //敌机移动
        this.transform.Translate (Vector3.down * speed * Time.deltaTime);
        if (transform.position.y <= posY) {
            Destroy (this.gameObject);
        }
        if (isDeath == true) {        //播放死亡动画

            timer += Time.deltaTime;
            int frameIndex = (int)(timer / (1f / frameCountPersconds));
            if (frameIndex >= explosionSprites.Length) {
                Destroy (this.gameObject);
            } else {
                render.sprite = explosionSprites [frameIndex];
            }        
        } 
//        else {        //播放受伤动画
//            if(type == EnumyType .middleEnemy || type == EnumyType .bigEnemy ){
//                if (hitTimer >0 ){
////                    Debug .Log ("hitTime" +hitTimer );
//                    hitTimer -=Time .deltaTime ;
////                    Debug .Log ("resetHitTime"+resetHitTime);
//                    int frameIndex = (int)((resetHitTime - hitTimer )/(1f/frameCountPersconds ));
//                    int frame = frameIndex %2;
////                    Debug .Log ("frame" + frame );
//                    render.sprite = hitSprites [frame];
//                }
//            }
//        }

    }

    public void BeHit ()        //被击中
    {
        hp -= 1;
        if (hp <= 0) {
            toDie ();
        }
//         else {
//            hitTimer = resetHitTime ;
//        }
    }
    private void toDie ()
    {    
        if (!isDeath) {
            isDeath = true;
            scoreShow .instance.score += score;
        }
    }
}

4.分数的记录显示与游戏的暂停

public enum GameState {
    Runing,
    Pause
}

public class scoreShow : MonoBehaviour {

    public static scoreShow instance ;

    public int score = 0;      //分数

    private GameObject findscrShow;
    private Text txt_score;

    public GameState gameState = GameState.Runing;


    // Use this for initialization
    void Start () {
        instance = this;
        //  txt_score = this.GetComponent<Text>();      //法1:获取到Text(手动挂在scroeShow下)
        findscrShow = GameObject.Find("scoreShow");      //法2  获取scroeShow后获取Text
        txt_score = findscrShow.GetComponent<Text>();
    }
    
    // Update is called once per frame
    void Update () {
        txt_score.text = "score:" + score;
    }

    public void transformGameState() {
        if (gameState == GameState.Runing ) {
            pauseGame();
        }
        else if (gameState==GameState.Pause ) {
            resumeGame();
        }
    }
    public void pauseGame() {
        Time.timeScale = 0;
        gameState = GameState.Pause;
    }
    public void resumeGame() {
        Time.timeScale = 1;
        gameState = GameState.Runing;
    }
}

暂停

public class gamePause : MonoBehaviour {

    private void OnMouseUpAsButton()
    {
        scoreShow .instance.transformGameState();
    }
}

 

2014-09-05 15:50:03 book_longssl 阅读数 1480


     今天我想和大家分享的是一个比较重要的组件——布娃娃(Ragdoll)。我们首先来看张图片吧!

 

          相信熟悉仙剑的朋友一定知道这样一句话:胜败乃兵家常事,大侠请重新来过。从仙剑一到仙剑五前传,仙剑带给我们的感动里不仅仅是一个个跌宕起伏、感人至深的故事,还有每一次战斗失败之后从头再来的勇敢。人生有时候就像游戏一样,我们总会遇到这样或着那样的挫折和困难。虽然在仙剑这样一个五灵六界的世界观下,人类基本作为最弱小的生命存在,但是每次我们的主角们不是一直在努力去做吗?所以我们的人生一定要积极向上,充满激情地去做一件事情。博主最讨厌的就是玩游戏玩到最后只剩下打嘴仗的这种玩家,游戏一定是有输有赢的,试问各位仙剑玩家哪一个没有被Boss虐过,可是游戏的乐趣不就是在于一遍遍地去超越自己吗?输不可怕,怕的是我们因为输了就丧失了努力的勇气。我觉得仙剑一直再像我们传递一种正能量,那就是我们一定要让自己勇敢,人生中有很多的事情或许我们都无法掌控,就像李逍遥剑术超凡却不能帮助灵儿逃脱宿命、云天河拥有神龙之息、后羿射日神弓,为救山下百姓而箭射琼华,却救不了心爱的女孩儿的性命、夏侯瑾轩以为 凡事尽心尽力就能做好,可是到最后他却只能拿匕首刺向瑕妹子,只是为了不让枯木占据她的身体。或许我们并不知道未来会是什么样子吧,但是至少在此时此刻,我们曾经努力过、我们很用心地做过某些事情,这样就够了。好了,我们不去评论这些玩家了,我们正式开始今天的内容。

         在RPG游戏中,当角色HP降低到0时,角色即进入了死亡状态,此时角色将倒在地上。在过去的游戏设计中,角色倒在地上的动作通常是由动画师绘制一定的动画来完成的,这种方式虽然简单,但是由于角色倒地的动作都是相同的,无法实时反映出角色受攻击的情况,所以在游戏开发领域逐渐形成了一种新的模型即布娃娃(Ragdoll),该模型就是用来模拟角色死亡的状态的。系统为我们提供了布娃娃组件,下面请大家和我一起来学习怎样使用布娃娃来模拟角色死亡的状态吧:

         首先我们创建一个新项目,在场景中创建一个Plane和平行光,接下来我们导入我们事先准备好的FBX模型,此时在游戏场景中应该可以看到下面的内容:


       接下来,我们选中模型Samuzai,为其创建一个布娃娃组件:


          我们一起来看打开的对话框:


        如果我们的模型中提供了骨骼动画的话,那么我们单击右侧的选择按钮就能找到相应的文件,然后我们点Create,此时模型下的骨骼组件应该会变成下面这个样子:


      我们将盒子碰撞器移除,将模型的动画设为None,现在我们来运行程序:


      可以看到,我们的角色很真实地倒在了地上,而且如果我们多次运行程序的话,会发现角色每次死亡的时候都是不一样的,这样大大增强了游戏的真实感,如果每次战斗死亡的姿势都是一样的,这样会不会视觉疲劳呢?虽然《轩辕剑6》的市场反响并不怎么样,然而得益于中的强大物理引擎,每次怪物死亡的时候都死得比较有范儿,大家可以自己去玩玩试玩版啊,哈哈。这里希望仙剑奇侠传的后续作品能够注意到这个问题,作为大侠,我们要死得轰轰烈烈的嘛,好了,这就是今天的文章了,希望大家喜欢!

Unity3D场景转换效果

阅读数 2650

unity3d中使用状态机

阅读数 3144

没有更多推荐了,返回首页