Unity作业

2D射击游戏

本科上unity课的一个算是大作业的东西吧,把它从有道笔记上统到博客上

生成敌人

    Instantiate(m_enemy,m_transform.position,Quaternion.identity);

飞船控制

	void Update () {
	
			
	        float movev=0;
	        float moveh=0;
	        if(Input.GetKey(KeyCode.UpArrow)){
	            movev-=speed*Time.deltaTime*10;
	        }
	        if(Input.GetKey(KeyCode.DownArrow)){
	            movev+=speed*Time.deltaTime*5;
	        }
	        if(Input.GetKey(KeyCode.LeftArrow)){
	            moveh+=speed*Time.deltaTime*8;
	        }
	        if(Input.GetKey(KeyCode.RightArrow)){
	            moveh-=speed*Time.deltaTime*8;
	        }
	        
	        m_transform.Translate(new Vector3(moveh,0,movev));
		
	        
	        m_rocketRate-=Time.deltaTime;
	            if(m_rocketRate<=0){
	                m_rocketRate=0.3f;
	                		if (Input.GetKey(KeyCode.Space) || (Input.GetMouseButton(0)))
							{
								Instantiate(m_rocket,m_transform.position,m_transform.rotation);
			
								m_audio.PlayOneShot(m_shootClip);
							}
	        }
		}

GUI

	void OnGUI(){
			GUI.skin.label.fontSize=48;
			
			GUI.skin.label.alignment=TextAnchor.LowerCenter;
			
			GUI.Label(new Rect(0,30,Screen.width,100),"SpaceWar");
			
			if(GUI.Button(new Rect(Screen.width*0.5f-100,Screen.height*0.7f,200,30),"Start!")){
				Application.LoadLevel("level1");
			}
		}

检测碰撞

	void OnTriggerEnter(Collider other)
	    {
	        if(other.tag.CompareTo("bound")==0)
	        {
	            m_life=0;
	            Destroy(this.gameObject);
	        }
	
	        else if(other.tag.CompareTo("PlayerRocket")==0)
	        {
	            Rocket rocket = other.GetComponent<Rocket>();
	            if(rocket!=null)
	            {
	                m_life-=rocket.m_power;
	                if(m_life<=0)
	                {
	                    Destroy(this.gameObject);
	                }
	            }
	        }
	        else if(other.tag.CompareTo("Player")==0)
	        {
	            m_life=0;
	            Destroy(this.gameObject);
	        }
			
			if(m_life<=0){
				GameManager.Instance.AddScore(m_point);
				Instantiate(m_explosionFX,m_transform.position,Quaternion.identity);
				
				Destroy(this.gameObject,0.1f);
			}
	    }

NO.2 第一人称射击

3D碰撞

  • 为场景添加碰撞体(实现物理碰撞)Component->Physics->Mesh Collider
    制作空主角(GameObject->Create Empty),Tag设为Player
    Tag在Edit->Project Setting中设置
  • 为主角添加角色控制器Physics->Character Controller,与场景碰撞产生交互(调整其碰撞体位置和大小,使主角覆盖)
  • 主角刚体组件Rigidbody 取消重力选项Use Gravity和Is Kinematic使其不受物理演算影响

控制主角

	public class Player : MonoBehaviour {
	
	//摄像机的Transform
		Transform m_camTransform;
	//摄像机旋转角度
		Vector3 m_camRot;
	//摄像机高度(主角高度)
		float m_camHeight = 1.4f;
	
	//主角Transform
		public Transform m_transform;
	
		//角色控制器组件
		CharacterController m_ch;
		float m_movSpeed=6.0f;//移动速度
		float m_gravity=2.0f;//重力
		public int m_life=5;//生命值
	
		Transform m_muzzlepoint;//枪口
		public LayerMask m_layer;//射击时,射线能碰到的碰撞层
		public Transform m_fx;//射中目标后的粒子效果
		public AudioClip m_audio;//射击音效
		float m_shootTimer=0;//射击间隔时间计时器
	
		void Start () {
			m_transform = this.transform;
			m_ch = this.GetComponent<CharacterController> ();//获取角色控制器组件
	
	//初始化摄像机,并锁定鼠标
			m_camTransform = Camera.main.transform;//获取摄像机
	//初始化摄像机位置
			Vector3 pos = m_transform.position; 
			pos.y += m_camHeight;
			m_camTransform.position = pos;
	//摄像机旋转方向与主角一致
			m_camTransform.rotation = m_transform.rotation;
			m_camRot = m_camTransform.eulerAngles;
	//锁定鼠标
			Screen.lockCursor = true;
	
			m_muzzlepoint = m_camTransform.Find ("M16/weapon/muzzlepoint").transform;//获取枪口位置
		}
		
		void Update () {//判断生命值是否为0
			if (m_life <= 0) 
				return;
			Control ();
	
			m_shootTimer -= Time.deltaTime;//更新射击间隔时间
			if (Input.GetMouseButton (0) && m_shootTimer <= 0)//鼠标左键射击 {
				m_shootTimer = 0.1f;
				//射击音效
				this.GetComponent<AudioSource> ().PlayOneShot(m_audio);
				GameManager.Instance.SetAmmo (1);//减少弹药,更新弹药UI
				RaycastHit info;//保存射线的探测结果
	
				Bool		hit=Physics.Raycast(m_muzzlepoint.position, m_camTransform.TransformDirection (Vector3.forward), out info, 100, m_layer);//射线只能与m_layer所指定的层碰撞
				if (hit) {
					if (info.transform.tag.CompareTo ("enemy") == 0)//如果射中了Tag为enemy的游戏体 {
						Enemy enemy = info.transform.GetComponent<Enemy> ();
						enemy.OnDamage (1);//减少敌人生命
					}
					Instantiate (m_fx, info.point, info.transform.rotation);//在射中的地方释放一个粒子效果
				}
			}
		}
	
		void Control (){
	//旋转摄像机,与主角位置保持一致
	//获取鼠标距离
			float rh = Input.GetAxis ("Mouse X");
			float rv = Input.GetAxis ("Mouse Y");
	//旋转摄像机
			m_camRot.x -= rv*5;
			m_camRot.y += rh*5;
			m_camTransform.eulerAngles = m_camRot;
	//主角面向方向与摄像机一致
			Vector3 camrot = m_camTransform.eulerAngles;
			camrot.x = 0;
			camrot.z = 0;
			m_transform.eulerAngles = camrot;
	//摄像机位置与主角一致
			Vector3 pos = m_transform.position;
			pos.y += m_camHeight;
			m_camTransform.position = pos;
	
	//控制移动的三个值xm,ym,zm
			float xm = 0, ym = 0, zm = 0;
			ym -= m_gravity * Time.deltaTime;//重力
	//控制上下左右运动W,S,A,D
			if (Input.GetKey (KeyCode.W)) {
				zm += m_movSpeed * Time.deltaTime;
			}
			else if (Input.GetKey (KeyCode.S)) {
				zm -= m_movSpeed * Time.deltaTime;
			}
	
			if (Input.GetKey (KeyCode.A)) {
				xm -= m_movSpeed * Time.deltaTime;
			}
			else if (Input.GetKey (KeyCode.D)) {
				xm += m_movSpeed * Time.deltaTime;
			}
	//使用角色控制器提供的Move函数进行移动,它会自动检测碰撞(局部坐标变为世界坐标)
			m_ch.Move (m_transform.TransformDirection (new Vector3 (xm, ym, zm)));
		}

绑定武器

  • 摄像机位置和旋转都设置为0
  • Clipping Planes/Near设为0.1,看到近处物体
  • 武器Prefab设置位置和旋转为0,处于摄像机层级下方,调整M16(武器)下一层级的weapon的位置角度
    敌人
  • 寻路,场景模型(level)确定Inspector中Static下拉菜单Navigation Static被选中,便于寻路
  • 打开Window->Navigation
    【Object】:若取消选中Nav Static,模型则不会被用作计算
    【Bake】:Radius和Height寻路者半径和高度
    Max Slope最大坡度
    Step Height楼梯最大高度
    Drop Height寻路者跳落的最大高度极限
    Jump Distance寻路者跳跃距离极限
  • 选择Bake对地形进行计算
  • 敌人Prefab,Component->Nav Mesh * * Agent将寻路组件指定给敌人(Radius和Height寻路者的半径和高度,Speed最大运动速度,Angular Speed最大旋转速度)
    Enemy脚本
	using System.Collections.Generic;
	
	public class Enemy : MonoBehaviour {
		Transform m_transform;
		Player m_player; //主角
		UnityEngine.AI.NavMeshAgent m_agent; //寻路组件
		float m_movespeed=1.5f; //移动速度
	
		Animator m_ani;//动画组件
		float m_rotSpeed=30;//角色旋转速度
		float m_timer=2;//计时器
		int m_life=5;//生命值
	
		protected EnemySpawn m_spawn;
	
		void Start () {
			m_transform = this.transform;
			m_ani = this.GetComponent<Animator> ();//获取动画组件
			m_player =GameObject.FindGameObjectWithTag ("Player").GetComponent<Player> ();//获得主角
			m_agent = GetComponent<UnityEngine.AI.NavMeshAgent> ();//获得寻路组件
			m_agent.speed = m_movespeed; //寻路器的行走速度
			m_agent.SetDestination (m_player.transform.position); //设置寻路目标
		}
	
	RotateTo函数使敌人始终转向面向主角的角度
		void RotateTo(){
			Vector3  targetdir = m_player.transform.position - m_transform.position;//获取目标方向
			Vector3 newDir = Vector3.RotateTowards (transform.forward, targetdir, m_rotSpeed * Time.deltaTime, 0.0f);//计算出新方向
			m_transform.rotation = Quaternion.LookRotation (newDir);//旋转至新方向(四元数)
		}
	敌人攻击和死亡(为敌人添加碰撞体Capsule Collider)
		public void OnDamage(int damage){
			m_life -= damage;
			print (m_life);
			if (m_life <= 0)
				m_ani.SetBool ("death", true);
		}
	
		void Update () {
			if (m_player.m_life <= 0)//如果主角生命为0
				return;
			AnimatorStateInfo stateInfo = m_ani.GetCurrentAnimatorStateInfo (0);//获取当前动画状态
			if (stateInfo.nameHash == Animator.StringToHash ("Base Layer.idle") && !m_ani.IsInTransition (0))//若处于待机状态 {
				m_ani.SetBool ("idle", false);
				//待机一定时间
				m_timer -= Time.deltaTime;
				if (m_timer > 0)
					return;
				
				if (Vector3.Distance (m_transform.position, m_player.m_transform.position) < 1.5f)//若距离主角小于1.5米,进入攻击动画状态{
					m_ani.SetBool ("attack", true);
				}
				else{
					m_timer = 1;//重置定时器
					m_agent.SetDestination (m_player.m_transform.position);//设置寻路目标点
					m_ani.SetBool ("run", true);//进入跑步动画状态
				}
			}
	
			if (stateInfo.nameHash == Animator.StringToHash ("Base Layer.run") && !m_ani.IsInTransition (0))//跑步状态 {
				m_ani.SetBool ("run", false);
	
				m_timer -= Time.deltaTime;//每隔1秒重新定位主角位置
				if (m_timer < 0) {
					m_agent.SetDestination (m_player.m_transform.position);
					m_timer = 1;
				}
	
				if (Vector3.Distance (m_transform.position, m_player.m_transform.position) < 1.5f)//如果距离主角小于1.5米,向主角攻击 {
					m_agent.Stop();//停止寻路
					m_ani.SetBool ("attack", true);//进入攻击状态
				}
			}
	
			if (stateInfo.nameHash == Animator.StringToHash ("Base Layer.attack") && !m_ani.IsInTransition (0)) //攻击状态{
				RotateTo ();//面向主角
				m_ani.SetBool ("attack", false);
				//如果动画播放完,重新进入待机状态
				if(stateInfo.normalizedTime>=1.0f){
					m_ani.SetBool ("idle", true);
					m_timer = 2;//重置计时器
	
					m_player.OnDamage (1);//更新主角的生命
				}
			}
			if (stateInfo.nameHash == Animator.StringToHash ("Base Layer.death") && !m_ani.IsInTransition (0))//死亡状态 {
				if (stateInfo.normalizedTime >= 1.0f) {
					m_spawn.m_enemyCount--;//更新敌人计数
					GameManager.Instance.SetScore (100);//加分
					Destroy (this.gameObject);//销毁
				}
			}
		}
		public void Init(EnemySpawn spawn)
		{
			m_spawn = spawn;
			m_spawn.m_enemyCount++;
		}
	}

设置动画

  • 敌人Prefab,组件Animator,取消选择Apply Root Motion,利用脚本控制动画
  • Windows->Animator,Parameters旁边的+,选择Bool,创建四个Bool值idle、run、attack、death;
  • 选择连线,如待机->跑步,在Conditions中将动画过渡条件设为run,bool值run设为true
  • 交互:添加碰撞层enemy和level,将enemy层指定给敌人;再创建Tag(enemy),指定给敌人;
  • 主角游戏体,添加Audio Source,Player脚本中将Layer设为enemy和level,射线可以击中敌人和场景,* Audio中加shot.WAV;
  • 创建AutoDestroy,指定给FX.Prefab
	public float m_timer=1.0f;
			void Start () {
			Destroy (this.gameObject, m_timer);
		}
	敌人出生,创建空物体,指定↓脚本并关联敌人的prefab
	public class EnemySpawn : MonoBehaviour {
		public Transform m_enemy;
		public int m_enemyCount = 0;
		public int m_maxEnemy = 3;
		public float m_timer=0;
		protected Transform m_transform;
	
			void Start () {
			m_transform = this.transform;
		}
			void Update () {
			if (m_enemyCount >= m_maxEnemy)//最大值
				return;
			//设定间隔时间
			m_timer -= Time.deltaTime;
			if (m_timer <= 0) {
				m_timer = Random.value * 15.0f;
				if (m_timer < 5)
					m_timer = 5;
				Transform obj = (Transform)Instantiate (m_enemy, m_transform.position, Quaternion.identity);//生成敌人
				Enemy enemy = obj.GetComponent<Enemy> ();//获取敌人脚本
				enemy.Init (this);//初始化敌人
			}
		}
	}

小地图

  • 创建新的Camera,使其在场景上方垂直向下,Projection:Orthographic,取消透视并调整Size值,调整Viewport Rect
  • 创建球体dummy,设为红色材质,将球体的Sphere Collider去掉(不需要实体)
  • 创建Layer(dummy),设置球体的Layer为dummy,将球体置于敌人prefab层级下
  • 选择主摄像机,取消显示dummy层;小地图摄像机,只显示level和dummy,指定脚本
	public class MiniCamera : MonoBehaviour {
		Camera m_camera;
	
		// Use this for initialization
		void Start () {
			float ratio = (float)Screen.width / (float)Screen.height;
			m_camera=this.GetComponent<Camera> ();
			m_camera.rect = new Rect ((1 - 0.2f), (1 - 0.2f * ratio), 0.2f, 0.2f * ratio);
		}
	}

No.3 塔防

游戏场景

  • Tool->Tile Creator设置格子大小,Create Tile …创建
    在Mesh Renderer中指定两种材质
  • 将场景模型的Layer指定为tile(新建),在Tile Object组件内指定Tile Layer为tile;选中Edit为编辑模式。选择不同的Material ID即可绘制
    选择Data,0无效格子;1敌人通过;2防守单位

UI

  • UI控件根据不同分辨率进行缩放component->Layout->Reference Resolution
  • 创建三个属性波数、铜钱、生命
  • 按钮UI->Button(Image下Souce Image设置按钮图片),在Button组件中,将Normal Color的Alpha值设为255使图片不透明

血条

  • 创建GameObject-UI-Canvas,渲染模式设置world space
  • 创建GameObject-UI-sidler,删除滑块部分,分别给背景和填充区域附图片,填充图片模式改为filled
  • 将血条存为prefab存在Resources中
  • 在血条对象脚本中先定义
	Transform m_lifebarObj;
	UnityEngine.UI.Slider m_lifebar;
  • 再在start中获取并初始化血条物体
	GameObject uiroot3d = GameObject.Find("Canvas1");
    GameObject prefab = (GameObject)Resources.Load("ui_lifebar");
    GameObject lifebarobj = (GameObject)Instantiate(prefab);
    m_lifebarObj = lifebarobj.transform;
    m_lifebarObj.parent = uiroot3d.transform;
    m_lifebarObj.localScale = new Vector2(0.01f, 0.01f);
    m_lifebar = m_lifebarObj.GetComponent<UnityEngine.UI.Slider>();
  • 血条减少动画
	void UpdateLifebar()
	    {
	
	        m_lifebar.value = (float)m_life / (float)m_maxlife;
	        Vector2 lifebarpos = this.transform.position;
	        lifebarpos.y += 0.7f;
	        m_lifebarObj.transform.position = lifebarpos;
	
	        m_lifebarObj.transform.eulerAngles = Camera.main.transform.eulerAngles;
	    }
  • 在死亡事件中销毁血条物体
	Destroy(m_lifebarObj.gameObject);

# 创建游戏中物体

	public static T Create<T>( Vector3 pos, Vector3 angle ) where T : Defender 
	{
		GameObject go = new GameObject();
		go.transform.position = pos;
		go.transform.eulerAngles = angle;
		go.name = "defender";
		T d = go.AddComponent<T>();
		d.Init();
	
		TileObject.get.setData(d.transform.position.x, d.transform.position.z, (int)TileStatus.LOCK)	
		return d;
	}
初始化模型资源,设置添加相关动画,设置委托控制动画
	public delegate void VoidDelegate();
	public event VoidDelegate m_action;
	public void SetAction(VoidDelegate act)
	{
		m_action = act;
	}
	protected virtual void Init()
	{
		m_attackArea = 2.0f;
		m_power = 2;
		CreateModel("swordman");
		m_action = Idle;
	}

Excel生成怪物

  • 读取xml文件
	void ReadXML()
	    {
	        m_spawnlist = new List<SpawnData>();
	
	        XMLParser xmlparse = new XMLParser();
	        XMLNode node = xmlparse.Parse(xmldata.text);
	
	        XMLNodeList list = node.GetNodeList("ROOT>0>table");
	        for (int i = 0; i < list.Count; i++)
	        {
	          
	            string wave = node.GetValue("ROOT>0>table>" + i + ">@wave");
	            string enemyname = node.GetValue("ROOT>0>table>" + i + ">@enemyname");
	            string level = node.GetValue("ROOT>0>table>" + i + ">@level");
	            string wait = node.GetValue("ROOT>0>table>" + i + ">@wait");
	
	            SpawnData data = new SpawnData();
	            data.wave = int.Parse(wave);
	            data.enemyname = enemyname;
	            data.level = int.Parse(level);
	            data.wait = float.Parse(wait);
	
	            m_spawnlist.Add(data);
	        }
	    }
  • 用生成的m_spawnlist数据做生成控制器
	 void SpawnEnemy()
	    {
	        if (m_index >= m_spawnlist.Count){
	            return;
	        }
	
	        m_timer -= Time.deltaTime;
	        if (m_timer > 0)
	            return;
	
	        SpawnData data = m_spawnlist[m_index];
	        if (GameManager.Instance.m_wave < data.wave )
	        {
	            if ( GameManager.Instance.m_EnemyList.Count > 0 )
	                return;
	            else
	                GameManager.Instance.SetWave(data.wave); 
	        }
	
	        m_index++;
	        if (m_index < m_spawnlist.Count)
	            m_timer = (m_spawnlist[m_index]).wait; 
	
	        GameObject enemymodel = Resources.Load<GameObject>(data.enemyname + "@skin");
	
	        GameObject enemyani = Resources.Load<GameObject>(data.enemyname + "@run");
	
	        Vector3 dir = m_startNode.transform.position - this.transform.position;
	        GameObject enmeyObj = (GameObject)Instantiate(enemymodel, this.transform.position,
	            Quaternion.LookRotation(dir));
	        enmeyObj.GetComponent<Animation>().AddClip(enemyani.GetComponent<Animation>().GetClip("run"), "run");
	
	
	        enmeyObj.GetComponent<Animation>()["run"].wrapMode = WrapMode.Loop;
	
	        enmeyObj.GetComponent<Animation>().CrossFade("run");
	
	        Enemy enemy = enmeyObj.AddComponent<Enemy>();
	
	        enemy.m_currentNode = m_startNode;
	
	        enemy.m_life = data.level * 3;
	        enemy.m_maxlife = data.level * 3;
	
	        m_liveEnemy++;
	
	        OnEnemyDeath(enemy, (Enemy e) =>
	        {
	            m_liveEnemy--;
	        });
	    }

记分

	创建GameManager脚本
	//静态实例
	public static GameManager Instance;
	//定义文本变量
	Text m_txt_score;
	//定义当前分数值
	public int m_score=0;
	//在初始化之前将实例赋给当前类
	void Awake(){
		Instance=this;
	}
	//在脚本当前控件对象下获取相应控件并初始化初值
	void Start () {
		foreach(Transform t in this.GetComponentsInChildren<Transform>()){
			if(t.name.CompareTo("score")==0){
				m_txt_score=t.GetComponent<Text>();
				m_txt_score.text=string.Format("分数:<color=blue>{0}</color>",m_score);
			}
		}
	}
	//改变分数函数(+=)
	public void SetScore(int score){
		m_score+=score;
		m_txt_score.text=string.Format("分数:<color=blue>{0}</color>",m_score);
	}

在积分对象判断死亡脚本片段上加

	if(m_life<0)
	{//加五分!
	            GameManager.Instance.SetScore(5);}

No.4 捕鱼游戏

2d资源切割

  • 使用SpriteEditor创建Sprite,【Edit】->【Project Setting】->【Editor】打开编辑器设置窗口,Default Beha Mode设为2D,Sprite Packer设为Always Enabled
  • 选择所需图片素材,将Sprite改为Multiple,打开Sprite Editor,“Slice”进行切割,将大炮Sprite轴心移动到炮的圆轴中心,将背景和大炮的Sprite放在场景中
资源在场景中的覆盖设置

Sorting Layers创建3个层background(背景)weapon(大炮),切割Sprite同时放入场景,制作动画,为动画制作prefab,存放至Resources文件夹中,Sorting Layers:fish(鱼)weapon(开火和爆炸)

鱼属性

    protected float m_moveSpeed=2.0f;//移动速度
    protected float m_life=10;//生命值
    public enum Target//枚举
    {
        Left=0,
        Right=1
    }
    public Target m_target=Target.Left;//移动目标
    protected Vector3 m_targetPosition;//目标位置

鱼初始化

    public delegate void VoidDelegate(Fish fish);
    public VoidDelegate OnDeath;
		//创建Fish实例
    public static Fish Create(GameObject prefab,Target target,Vector3 pos)
    {
     GameObject go=(GameObject)Instantiate(prefab,pos,Quaternion.identity);
        Fish fish=go.AddComponent<Fish>();
        fish.Init(target);
        return fish;
    }
    void Init(Target target)
    {
        m_target=target;
    }
    

    void UpdatePosition()//更新位置
	Vector3 pos=Vector3.MoveTowards(this.transform.position,m_targetPosition,m_moveSpeed*Time.deltaTime);
			//向目标位置移动
    if(Vector3.Distance(pos,m_targetPosition)<0.1f)
    {
  //三元控制
        m_target=m_target==Target.Left?Target.Right:Target.Left;
        SetTarget();
    }
    this.transform.position=pos;
	void SetTarget()//设置目标
	{
	    float rand=Random.value;//随机
	    Vector3 scale=this.transform.localScale;
	    scale.x=Mathf.Abs(scale.x)*(m_target==Target.Right?1:-1);
	    this.transform.localScale=scale;
	    float cameraz=Camera.main.transform.position.z;//获得摄像机z轴位置
	m_targetPosition=Camera.main.ViewportToWorldPoint(new
	Vector3((int)m_target,1*rand,-cameraz));//设置目标位置}
	}

鱼生成

{
    public float timer=0;//计时器
    public int max_fish=30;//最大生成数量
    public int fish_count=0;//当前鱼的数量
    void Update () {
        timer-=Time.deltaTime;
        if(timer<=0)
        {
            timer=2.0f;//重新计时
            if(fish_count>=max_fish)
                return;
        
        int index=1+(int)(Random.value*3.0f);//随机产生不同的鱼
        if(index>3){
            index=3;
        }
        fish_count++;//更新鱼的数量
        GameObject fishprefab=(GameObject)Resources.Load("fish"+index);//读取鱼的prefab
        float cameraz=Camera.main.transform.position.z;//获取摄像机z轴位置
//鱼初始位置
        Vector3 randpos=new Vector3(Random.value,Random.value,-cameraz); 
        randpos=Camera.main.ViewportToWorldPoint(randpos);
//鱼的随机初始方向
        Fish.Target target=Random.value>0.5f?Fish.Target.Right:Fish.Target.Left; 
			//创建鱼的实例
        Fish f=Fish.Create(fishprefab,target,randpos);
			//注册鱼的死亡消息
        f.OnDeath+=OnDeath;
        }
    }
    void OnDeath(Fish fish)
    {
        fish_count--;}
	}

子弹Fire

	{
	    float m_moveSpeed=10.0f;//移动速度
			//创建子弹
	    public static Fire Create(Vector3 pos,Vector3 angle)
	    {
	        GameObject prefab=Resources.Load<GameObject>("fire");
	        GameObject fireSprite=(GameObject)Instantiate(prefab,pos,Quaternion.Euler(angle));//子弹实例
	        Fire f=fireSprite.AddComponent<Fire>();
	        Destroy(fireSprite,2.0f);//2秒销毁自己
	        return f;
	    }
	void Update () {//更新子弹位置
	        this.transform.Translate(new Vector3(0,m_moveSpeed*Time.deltaTime,0));
		}
	}

大炮Canon

	{	
	    float m_shootTimer=0;
		void Update () {
	    m_shootTimer-=Time.deltaTime;
	    UpdateInput();
	}
	void UpdateInput()
	{
	    Vector3 ms=Input.mousePosition;//鼠标位置
	    ms=Camera.main.ScreenToWorldPoint(ms);
	    Vector3 mypos=this.transform.position;//大炮位置
	    if(Input.GetMouseButton(0))//左键开火
	    {	//计算鼠标位置与大炮位置之间的角度
	        Vector2 targetDir=ms-mypos;
	        float angle=Vector2.Angle(targetDir,Vector3.up);
	        if(ms.x>mypos.x)
	            angle=-angle;
	        this.transform.eulerAngles=new Vector3(0,0,angle);
	        if(m_shootTimer<=0)
	        {
	            m_shootTimer=0.1f;
	//开火,创建子弹实例
	            Fire.Create(this.transform.TransformPoint(0,1,0),new Vector3(0,0,angle));
	        }
	    }
	}

碰撞:

	void OnTriggerEnter2D(Collider2D other)
    {
         Fish f=other.GetComponent<Fish>();
         if(f==null)
             return;
         else
             f.SetDamage(1);
         Destroy(this.gameObject);
 	}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值