结构图:

  

两个场景,一个是开始界面。一个是游戏界面:

脚本说明:依次是:敌人脚本,主角游戏,主菜单,工具

Enemy

 using UnityEngine;
using System.Collections; public class Enemy : MonoBehaviour
{ /*===============================
* 敌人脚本
*==============================*/ //敌人状态 //敌人站立状态
public const int STATE_STAND = ;
//敌人行走状态
public const int STATE_WALK = ;
//敌人奔跑状态
public const int STATE_RUN = ;
//敌人暂停状态
public const int STATE_PAUSE = ; //记录敌人当前状态
private int enemState;
//主角对象
private GameObject hero; //备份上一次敌人的思考时间
private float backUptime;
//敌人思考下一次行为时间
private const int AI_ATTACK_TIME = ;
//敌人的巡逻范围
public const int AI_ATTACK_DISTANCE = ; //是否绘制血条 当鼠标指向敌人则绘制。离开则不绘制
bool showBlood = false; //血条资源贴图
public Texture2D tex_red;
public Texture2D tex_black; //生命值贴图
public Texture2D tex_hp; //生命值
private int HP = ; //敌人仇恨
private bool ishatred = false; //图片数字资源
Object[] texmube; // Use this for initialization
void Start()
{
//获取主角对象,这里前端赋值比较好
hero = GameObject.Find("Hero"); //读取图片资源
texmube = Resources.LoadAll("number"); //设置敌人默认状态为站立
enemState = STATE_STAND;
} // Update is called once per frame
void Update()
{
//判断敌人与主角之间的距离
if (Vector3.Distance(transform.position, hero.transform.position) < AI_ATTACK_DISTANCE || ishatred)
{
//敌人进入奔跑状态
gameObject.animation.Play("run");
enemState = STATE_RUN; //设置敌人面朝主角方向
transform.LookAt(hero.transform); //随机攻击主角
int rand = Random.Range(, );
if (rand == )
{
//模拟攻击,
//向主角发送攻击消息,然后在主角对象脚本中实现HeroHrut方法,进行主角减血
hero.SendMessage("HeroHurt");
}
}
//敌人进入巡逻状态
else
{
//计算敌人的思考时间
if (Time.time - backUptime >= AI_ATTACK_TIME)
{
//敌人开始思考
//备份思考的时间
backUptime = Time.time; //取得0~2之间的随机数
int rand = Random.Range(, );
if (rand == )
{
//敌人进入站立状态
transform.animation.Play("idle");
//设置状态
enemState = STATE_STAND;
}
else if (rand == )
{
//敌人进入行走状态
//敌人随机旋转角度
Quaternion rotate = Quaternion.Euler(, Random.Range(, ) * , );
//1秒内完成旋转
transform.rotation = Quaternion.Lerp(transform.rotation, rotate, Time.deltaTime * );
//播放行走动画
transform.animation.Play("walk");
enemState = STATE_WALK;
} }
}
switch (enemState)
{
case STATE_STAND: break;
case STATE_WALK:
//敌人行走
transform.Translate(Vector3.forward * Time.deltaTime);
//gameObject.animation.Play("walk");
break;
case STATE_RUN:
//敌人朝向主角奔跑,当相距2时,就不向前跑了
if (Vector3.Distance(transform.position, hero.transform.position) > )
{
transform.Translate(Vector3.forward * Time.deltaTime * );
}
break;
}
}
void OnGUI()
{
if (showBlood)//如果绘制血条
{
//绘制生命值贴图
GUI.DrawTexture(new Rect(, , tex_hp.width, tex_hp.height), tex_hp);
//绘制主角生命值
Tools.DrawImageNumber(, , HP, texmube); //绘制敌人血条
int blood_width = tex_red.width * HP / ;
//绘制黑色血条 即底色
GUI.DrawTexture(new Rect(, , tex_black.width, tex_black.height), tex_black);
//绘制红色血条
GUI.DrawTexture(new Rect(, , blood_width, tex_red.height), tex_red);
}
} /// <summary>
/// 当在敌人上单击鼠标左键
/// </summary>
void OnMouseDown()
{
//击中敌人目标
if (HP > )
{
//减掉5点血
HP -= ;
//被击打时,后退
transform.Translate(Vector3.back * );
//击中敌人后立即进入战斗状态
ishatred = true;
}
else//敌人死亡
{
//敌人死亡
Destroy(gameObject);
//发送死亡消息
hero.SendMessage("EnemyHurt");
}
}
void OnMouseUp()
{
//击打后退还原
transform.Translate(Vector3.forward * Time.deltaTime * );
}
void OnMouseOver()
{
//开始绘制血条
showBlood = true;
}
void OnMouseExit()
{
//结束绘制血条
showBlood = false;
}
}

Game

 using UnityEngine;
using System.Collections; public class Game : MonoBehaviour
{
/*===============================
* 主角脚本
*==============================*/ //游戏状态机 //游戏中状态
public const int STATE_GAME = ;
//游戏胜利状态
public const int STATE_WIN = ;
//游戏失败状态
public const int STATE_LOSE = ; //枚举角色鼠标位置
public enum RotationAxes { MouseXAndY = , MouseX = , MouseY = }
public RotationAxes axes = RotationAxes.MouseXAndY;
float rotationY = 0f; //鼠标准心
public Texture2D tex_fire; //血条资源贴图
public Texture2D tex_red;
public Texture2D tex_black; //生命值贴图
public Texture2D tex_hp; //战斗胜利资源贴图
public Texture2D tex_win;
//战斗失败资源贴图
public Texture2D tex_lose;
//游戏音乐资源
public AudioSource music; //主角生命值
public int HP = ; //图片数字资源
Object[] texmuber; //当前游戏状态
int gameState; // Use this for initialization
void Start()
{
//取消默认鼠标图标
Screen.showCursor = false;
//读取图片资源
texmuber = Resources.LoadAll("number");
//设置默认状态为游戏中
gameState = STATE_GAME; if (rigidbody) //如果是刚体
/*
如果freezeRotation被启用,旋转不会被物体模拟修改。
* 这对于创建第一人称射击游戏时是很有用的,因为玩家需要使用鼠标完全控制旋转。
*/
rigidbody.freezeRotation = true;////冻结旋转
} // Update is called once per frame
void Update()
{
switch (gameState)
{
case STATE_GAME: UpdateGame(); break;
case STATE_WIN:
case STATE_LOSE:
if (Input.GetKey(KeyCode.Escape))
{
Application.LoadLevel("Menu");
}
break;
default:
break;
}
} void OnGUI()
{
switch (gameState)
{
case STATE_GAME:
RenderGame();
break;
case STATE_WIN:
GUI.DrawTexture(new Rect(, , tex_win.width, tex_win.height), tex_win);
break;
case STATE_LOSE:
GUI.DrawTexture(new Rect(, , tex_lose.width, tex_lose.height), tex_lose);
break;
default:
break;
}
} private void RenderGame()
{
if (tex_fire)
{
//绘制鼠标准心
float x = Input.mousePosition.x - tex_fire.width / ;
float y = Screen.height - Input.mousePosition.y - tex_fire.width / ; GUI.DrawTexture(new Rect(x, y, tex_fire.width, tex_fire.height), tex_fire);
} //绘制主角血条
int blood_width = tex_red.width * HP / ;
GUI.DrawTexture(new Rect(, Screen.height - , tex_black.width, tex_black.height), tex_black);
GUI.DrawTexture(new Rect(, Screen.height - , blood_width, tex_red.height), tex_red); //绘制生命值贴图
GUI.DrawTexture(new Rect(, Screen.height - , tex_hp.width, tex_hp.height), tex_hp); //绘制主角生命值
Tools.DrawImageNumber(, Screen.height - , HP, texmuber);
} /// <summary>
/// 主角被攻击
/// </summary>
void HeroHurt()
{
HP--;
if (HP <= )
{
HP = ;
gameState = STATE_LOSE; //游戏失败
}
} /// <summary>
/// 碰到道具血条加血
/// </summary>
void HeroAddBlood()
{
HP += ;
if (HP >= )
{
HP = ;
}
}
/// <summary>
/// 敌人被攻击
/// </summary>
void EnemyHurt()
{
//找到所有的NPC
GameObject[] enemy = GameObject.FindGameObjectsWithTag("enemy");
//Debug.Log(enemy.Length); //敌人对象数字长度为1表示敌人全部死亡
if (enemy.Length == )
{ gameState = STATE_WIN;
}
}
private void UpdateGame()
{
if (Input.GetKey(KeyCode.Escape))
{
Application.LoadLevel("Menu");
}
//计算摄像机旋转
if (axes == RotationAxes.MouseX)
{
//旋转角色
transform.Rotate(, Input.GetAxis("Mouse X"), );
}
else
{
//设置角色欧拉角
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, );
}
} /// <summary>
/// 在移动的时,当controller碰撞到collider时OnControllerColliderHit被调用。
/// </summary>
/// <param name="hit"></param>
void OnControllerColliderHit(ControllerColliderHit hit)
{
//获取角色控制器碰撞到的游戏对象
GameObject collObj = hit.gameObject; //是否为加血的箱子对象
if (collObj.name == "Cube")
{
//主角加血
HeroAddBlood();
//销毁箱子
Destroy(collObj);
}
} }

Menu

 using UnityEngine;
using System.Collections; public class Menu : MonoBehaviour { /*===============================
* 主菜单脚本
*==============================*/ //游戏界面状态机 //主菜单界面
public const int STATE_MAINMENU = ;
//游戏设置界面
public const int STATE_OPTION = ;
//游戏帮助界面
public const int STATE_HELP = ;
//游戏退出界面
public const int STATE_EXIT = ;
//GUI皮肤
public GUISkin mySkin; //游戏背景贴图
public Texture textureBG;
//开始菜单贴图
public Texture tex_startInfo;
//帮助菜单贴图
public Texture tex_helpInfo; //游戏音乐资源
public AudioSource music;
//当前游戏状态
private int gameState; // Use this for initialization
void Start()
{
//初始化游戏状态为主菜单界面
gameState = STATE_MAINMENU;
} // Update is called once per frame
void Update()
{ }
void OnGUI()
{
switch (gameState)
{
case STATE_MAINMENU:
//绘制主菜单界面
RenderMainMenu();
break;
case STATE_OPTION:
//绘制游戏设置界面
RenderOption();
break;
case STATE_HELP:
//绘制游戏帮助界面
RenderHelp();
break;
case STATE_EXIT:
//绘制游戏退出界面
//目前直接关闭并退出游戏
break;
default:
break;
}
}
/// <summary>
/// 绘制游戏帮助界面
/// </summary>
private void RenderHelp()
{
GUI.skin = mySkin;
GUI.DrawTexture(new Rect(, , Screen.width, Screen.height), tex_helpInfo);
//返回按钮
if (GUI.Button(new Rect(, , , ), "", "back"))
{
gameState = STATE_MAINMENU;
}
}
/// <summary>
/// 绘制游戏设置界面
/// </summary>
private void RenderOption()
{
GUI.skin = mySkin;
GUI.DrawTexture(new Rect(, , Screen.width, Screen.height), textureBG); //开启音乐按钮
if (GUI.Button(new Rect(, , , ), "", "music_on"))
{
if (!music.isPlaying)
{
//播放音乐
music.Play();
}
}
//关闭音乐按钮
if (GUI.Button(new Rect(, , , ), "", "music_off"))
{
//关闭音乐
music.Stop();
}
//返回按钮
if (GUI.Button(new Rect(, , , ), "", "back"))
{
gameState = STATE_MAINMENU;
}
}
/// <summary>
/// 绘制主菜单界面
/// </summary>
private void RenderMainMenu()
{
//设置界面皮肤
GUI.skin = mySkin;
//绘制游戏背景图
GUI.DrawTexture(new Rect(, , Screen.width, Screen.height), textureBG); //开始游戏按钮
if (GUI.Button(new Rect(, , , ), "", "start"))
{
//进入开始游戏状态
Application.LoadLevel("Game");
}
//游戏选项按钮
if (GUI.Button(new Rect(, , , ), "", "option"))
{
//处于开始游戏状态
gameState = STATE_OPTION;
}
//游戏帮助按钮
if (GUI.Button(new Rect(, , , ), "", "help"))
{
//进入游戏帮助状态
gameState = STATE_HELP;
}
//游戏退出按钮
if (GUI.Button(new Rect(, , , ), "", "exit"))
{
//退出游戏
Application.Quit();
}
}
}

Tools

 

 using UnityEngine;
using System.Collections; public class Tools : MonoBehaviour
{ /*===============================
* 工具脚本
*==============================*/ /// <summary>
///
/// </summary>
/// <param name="x">绘制数字 x坐标</param>
/// <param name="y">绘制数字 y坐标</param>
/// <param name="number">需要绘制的数字</param>
/// <param name="texnumber">绘制图片数组资源</param>
public static void DrawImageNumber(int x, int y, int number, Object[] texnumber)
{
//将整数数据转换为字符数组
char[] chars = number.ToString().ToCharArray();
//计算图片的宽度与高度,因为每张图片都是一样大。所以这里获取第一张即可
Texture2D tex = (Texture2D)texnumber[];
int width = tex.width;
int height = tex.height; //遍历字符数组
foreach (char item in chars)
{
//得到每一位整型数组
int i = int.Parse(item.ToString());
//绘制图片数字
GUI.DrawTexture(new Rect(x, y, width, height), texnumber[i] as Texture2D);
x += width;
}
} }

注意事项:NPC需要添加标签:enemy

游戏源码:

http://pan.baidu.com/s/1ntmOQnf

unity3d-游戏实战突出重围,整合游戏的更多相关文章

  1. Unity 4.2.0 官方最新破解版(Unity3D 最新破解版,3D游戏开发工具和游戏引擎套件)

    Unity是一款跨平台的游戏开发工具,从一开始就被设计成易于使用的产品.作为一个完全集成的专业级应用,Unity还包含了价值数百万美元的功能强大的游戏引擎.Unity作为一个游戏开发工具,它的设计主旨 ...

  2. Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录

    一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...

  3. OpenNI结合Unity3D Kinect进行体感游戏开发(转)

    OpenNI结合Unity3D Kinect进行体感游戏开发(转) 楼主# 更多 发布于:2012-07-17 16:42     1. 下载安装Unity3D(目前版本为3.4)2. 下载OpenN ...

  4. Swift语言实战晋级-第9章 游戏实战-跑酷熊猫-1

    学习目标 一.进一步学习Swift的游戏制作 二.掌握SKNode,SKSpriteNode的运用 三.了解SpriteKit的物理系统 四.掌握动作(SKAction)的运用 在这一章,我们要通过制 ...

  5. Swift游戏实战-跑酷熊猫 14 熊猫打滚

    这节内容我们来实现熊猫打滚.思路是这样的,当熊猫起跳时记录他的Y坐标,落到平台上的时候再记录它的Y坐标.两个坐标之间的差要是大于一定数值就判断它从高处落下要进行打滚缓冲.至此跑酷熊猫已经像一个游戏的样 ...

  6. Swift游戏实战-跑酷熊猫 13 二段跳的实现

    这节内容我们来实现熊猫的二段跳. 要点: 二段跳的逻辑: 逻辑一,第一次点击屏幕,status就会变成jump. 逻辑二,第二次点击屏幕,status就会变成jump2. 逻辑三,当status变成j ...

  7. Swift游戏实战-跑酷熊猫 12 与平台的碰撞

    这节主要实现熊猫和平台的碰撞,实现熊猫在平台上奔跑 要点 对平台进行物理属性设置 //设置物理体以及中心点 self.physicsBody = SKPhysicsBody(rectangleOfSi ...

  8. Swift游戏实战-跑酷熊猫 11 欢迎进入物理世界

    物理模拟是一个奇妙的事情,以此著名的游戏有愤怒的小鸟.我们在这节将会一起来了解如何设置重力,设置物理包围体,碰撞的检测. 要点: 设置物理检测的代理: 让主场景遵循SKPhysicsContactDe ...

  9. Swift游戏实战-跑酷熊猫 10 视差滚动背景

    原理 实现 勘误 “实现”的视频中有个错误,如下 背景移动时有个错误,看红色部分,近景归位时,第二张图片的下标是1 if arrBG[0].position.x + arrBG[0].frame.wi ...

  10. Swift游戏实战-跑酷熊猫 09 移除场景之外的平台

    上一节,我们写出了一个疯狂产生平台的东西.所谓上帝欲使其灭亡,必先使其疯狂.所以太疯狂都不是什么好事,所以我们要采取一些措施,例如移除场景之外的平台.btw如果哪天你觉得自己的老板行为乖张,难以理喻. ...

随机推荐

  1. SQL Server2012远程访问设置

    http://jingyan.baidu.com/article/a681b0de3bdb7b3b19434667.html?qq-pf-to=pcqq.group 1.打开SQL server201 ...

  2. linux下python3.5环境搭建

    ubuntu12 在虚拟机vm11版本下安装正常,ubuntu14在虚拟机11-14版本下均因为某些文件权限不够安装失败(ubuntu14安装失败),未解决. ubuntu12 安装完成后,首先安装 ...

  3. authentication plugin caching_sha2

    操作系统:windows 10 mysql版本:mysql  Ver 8.0.11 for Win64 on x86_64 (MySQL Community Server - GPL) 安装完mysq ...

  4. 【魔改】hdu6325 多校赛3G xy排序凸包+llvector模板

    凸包算法前的预处理,可以极角排序,也可以按X,Y轴排序, 极角排序需要找到角落里的一个点,Xy轴排序要跑两遍凸包 而本题的要求只要一个上半凸包,并且有X轴从小到大以及字典序限制,完全符合xy排序,直接 ...

  5. Microsoft .NET Framework

    Microsoft .NET Framework是用于Windows的新托管代码编程模型.它将强大的功能与新技术结合起来,用于构建具有视觉上引人注目的用户体验的应用程序,实现跨技术边界的无缝通信,并且 ...

  6. beginner’s mistake

    PHP Advanced and Object-Oriented Programming 3rd Edition Related to modularity is abstraction: class ...

  7. iOS开发 - 事件传递响应链

    序言 当我们在使用微信等工具,点击扫一扫,就能打开二维码扫描视图.在我们点击屏幕的时候,iphone OS获取到了用户进行了“单击”这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UI ...

  8. tensorflow入门笔记(三) tf.GraphKeys

    tf.GraphKeys类存放了图集用到的标准名称. 该标准库使用各种已知的名称收集和检索图中相关的值.例如,tf.Optimizer子类在没有明确指定待优化变量的情况下默认优化被收集到tf.Grap ...

  9. fiddler抓包常用功能详解

    一.基础部分: 1.设置代理ip及端口,tools --> telerik fiddler options --> connections -->勾选 “ Allow romote ...

  10. 跨域的问题(nginx解决才是王道)

    跨域分为两类:一时get跨域,而是post跨域.常见的是三种: 一种是jsonp, $.ajax({ url: "http://127.0.0.1/~chenjiebin/mycode/ph ...