2016-07-12 16:00:39 qq_15267341 阅读数 990
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

1 Icon
这里写图片描述


发布后的效果:
这里写图片描述


2 Splash Image
这里写图片描述


发布后的效果:
这里写图片描述


3 show unity splash screen
这里写图片描述


发布后的效果:
这里写图片描述


4 default icon
这里写图片描述


发布后的效果:
这里写图片描述


5 其他的
这里写图片描述


这里写图片描述


如果是对外发布Android App的,还需要注意如下:

这里写图片描述


这里写图片描述


FR:海涛高软(QQ群:386476712)

2017-03-02 22:03:02 jessssion 阅读数 3056
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

制作敌人简单AI和发射火球

写在前面:
- 学习课本:Unity5实战 使用c#和unity开发多平台游戏-作者:Joseph Hocking
- 内容:第三章
-unity3d学习(一)制作第一人称射击-玩家的视口和移动
-unity3d学习(二)制作第一人称射击-玩家的视口和移动


简单的敌人自动移动(AI)和死亡

第一步:创建一个新脚本 Wandering
给敌人添加Wandering 脚本,并输入以下代码
using UnityEngine;
using System.Collections;

public class Wandering: MonoBehaviour 
{
    public float speed = 3.0f;
    public float obstacleRnage = 5.0f;

    private bool _alive;//判断用户是否存活
    void Start () {
        _alive = true;
    }

    void Update()
    {
        if(!_alive)
        {
            return;//如果没有活着,则停止运行下面代码
        }
        transform.Translate(0,0,speed*Time.deltaTime);//保持每帧向前移动

        Ray ray = new Ray(transform.position,transform.forward);//向前面发射一条射线
        RaycastHit hit;
        if(Physics.SphereCast(ray,0.75f,out hit))
        {
            if(hit.distance<obstacleRnage)
            {
                float angle = Random.Range(-110,110);
                transform.Rotate(0,angle,0);
            }
        }
    }

    public void setAlive(alive)
    {
        _alive = alive;
    }
}
第二步:修改ReactiveTarget脚本
...
public void ReactToHit()
{
    wanderingAI behavior = GetCompent<WanderingAI>()
    if(behavior)
    {
        behavior.setAlive(false);
    }
    StartCoroutine(Die());
}
...
第三步:给敌人创建预设
添加一个预设体,以便我们后面添加此物体
第四步:添加一个不可见的SceneController空对象
在SceneController中添加SceneController脚本,使当玩家击杀一个敌人,再次生成一个新的敌人
using UnityEngine;
using System.Collections;

public class SceneController: MonoBehaviour 
{
    [SerializeField] private GameObject enemyPrefab;//序列化预设对象
    private GameObject _enemy;

    void Update()
    {
        if(_enemy==null)
        {
            _enemy = Instantiate(enemyPrefab) as GameObject;
            _enemy.transform.position = new Vector3(0,1,0);
            float angle = Random.Range(0,360);
            _enmey.transform.Rotate(0,angle,0);
        }
    }
}

让敌人见到玩家发射火球

第一步:制作一个火球预设体
这里写图片描述
修改WanderingAI代码,使敌人见到玩家发射一个火球
    ...
    [SerizeField] private GameObject fireballPrefab;
    private GameObject _fireball;
    ...
    if(physics.SphereCat(ray,0.75f,out hit))
    {
        GameObject hitObject = hit.transform.gameObject;
        if(hitObject.GetComponent<PlayerCharacter>())//检测是否时玩家
        {
            if(_fireball == null)//检测是否已经发射火球了
            {
                _fireball = Instantiate(fireballPrefab) as GameObject;
                _fireball.transform.position = transform.TransformPoint(Vector3.forward*1.5f);//把相对与此物体的坐标转化为全局坐标
            }
        }
        else if(hit.distance<obstacleRange)
        {
            float angle = Random,Range(-110,110);
            transform.Rotate(0,angle,0);
        }
    }
    ...
第二步:为球体的Sphere Collider组件的I上Trigger复选框勾上,并为其添加Rigidbody刚体,取消UseGravity选项。再添加Fireball脚本给火球
using UnityEngine;
using System.Collections;

public class Fireball : MonoBehaviour {
    public float speed = 10.0f;
    public int damage = 5;

    void Start () {

    }

    // Update is called once per frame
    void Update () {
        transform.Translate(0,0,speed*Time.deltaTime);
    }

    void OnTriggerEnter(Collider other)
    {
        PlayerCharacter player = other.GetComponent<PlayerCharacter>();
        if (player != null)
        {
            //Debug.Log("Player hit");
            player.Hurt(damage);
        }
        Destroy(this.gameObject);
    }
}
第三步:为玩家添加PlayCharacter,来记录和计算玩家受到的伤害
using UnityEngine;
using System.Collections;

public class PlayerCharacter : MonoBehaviour {
    private int _health;

    void Start () {
        _health = 5;
    }

    public void Hurt(int damage)
    {
        _health -= damage;
        Debug.Log("Health:"+_health);
    }
}

注意:很多类和方法不清楚请查看官方文档

2013-02-04 10:33:21 yang7474020 阅读数 845
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

这个流程主要实现以下功能:界面上显示玩家当前的总血量,当被其他玩家发射的子弹打中后,会减1格血,血量为0时判定为死亡,会重置玩家的位置到出生点,并且重设血量为最大血量。

实现这个逻辑,分了以下几个步骤。

1.维护玩家血量相关信息。

首先玩家血量要用图形化在界面上显示,首先需要在场景中建立一个GUITexture,这里起名为GUI_heart,来表示当前血量图片。为了控制血量的显示,为GUI_heartf附加了一个控制脚本,名为HeartControl.cs。这个脚本的内容如下:

01.using UnityEngine;
02.using System.Collections;
03.
04.public class HeartControl : MonoBehaviour {
05.    public Texture2D[] heartImageArray;
06.    private const int maxLives = 5;
07.    private static int lives = maxLives;
08.
09.    public static void DecreaseLive()
10.    {
11.        lives--;
12.        if(lives==0)
13.        {
14.            lives=maxLives;
15.            PlayerManager.selfPlayer.position = GameObject.Find("SpwanPlayer").transform.position;
16.        }
17.    }
18.    // Use this for initialization
19.    void Start () {
20.
21.    }
22.
23.    // Update is called once per frame
24.    void Update () {
25.        if(PlayerManager.selfPlayer!=null)
26.        {
27.            guiTexture.enabled = true;
28.            guiTexture.texture = heartImageArray[lives-1];
29.        }
30.        else
31.        {
32.            guiTexture.enabled = false;
33.        }
34.
35.
36.    }
37.}

这里heartImageArray表示不同血量所对应的血量图片,血量用心型图标来显示,5格血就是5颗心。把这个数组声明为public,可以在编辑器中,设置这个数组的尺寸,以及每个入口点所对应的图片,十分方便。

maxLives就是最大血量有5格血,lives是当前人物的血量。

在每帧更新函数Update()中,首先检查当前玩家的变量是否为空,为空可能是因为是Server端,这种情况下就不需要显示血量,因此将图片设为false:guiTexture.enabled = false;

如果不为空,那么将根据当前血量的值,把对应数组中的图片赋值给这个guiTexture当前的texture,这样就实现图片随血量值的变化而变化。

这里PlayerManager.selfPlayer中的PlayerManager我自己建立的一个全局的静态类,维护了唯一的静态变量private static Transform _selfplayer,代表客户端所对应的玩家自己。这个类可以被所有脚本所访问,访问起来十分方便,实现如下:

01.using UnityEngine;

02.using System.Collections;

03.using System;

04.

05.public static class PlayerManager  {

06.

07.    private static Transform _selfplayer = null;

08.    public static Transform selfPlayer

09.    {

10.        get

11.        {

12.            return _selfplayer;

13.        }

14.        set

15.        {

16.            _selfplayer = value;

17.

18.        }

19.    }

20.

21.}

后期随着逻辑的复杂,可以为这个脚本的玩家增加更多的数据来维护。

然后是DecreaseLive函数,这个函数可以被外部所调用,给玩家减血,调用后,自动扣除一滴血,为0时,正如规定的一样,重设玩家血量为最大血量,并且找到重生点的位置,将玩家位置重置。

2.控制子弹打中玩家的逻辑

实现大体流程是先给玩家的人物身上附加一个释放子弹的脚本,当客户端自己的玩家按键触发技能时,就调用一个网络上的RPC,告诉所有客户端和服务器在本地创建一个飞行的子弹。并且在这个人物脚本里添加一个响应人物碰撞的事件函数,然后检查是不是碰撞的对象是子弹,而且不是这个人物所发射的,如果检测成功,就调用HeartControl脚本的减血函数。

这个脚本名为Shoot.cs,实现如下:

001.using UnityEngine;

002.using System.Collections;

003.

004.public class Shoot : MonoBehaviour

005.{

006.    public Texture skillTex1;

007.    public Texture skillTex2;

008.    public Transform bulletPrefab;

009.    public Transform explosionEffect;

010.    public AnimationClip attackAnim;

011.

012.    // Use this for initialization

013.    void Start ()

014.    {

015.

016.    }

017.

018.    // Update is called once per frame

019.    void Update ()

020.    {

021.        if (networkView.isMine && Input.GetKeyUp ("2")) {

022.            ShootBullet ();

023.

024.        }

025.            if (networkView.isMine && Input.GetKeyUp ("3")) {

026.            ExplosiveEffect();

027.

028.        }

029.

030.    }

031.

032.    void OnGUI ()

033.    {

034.        if (networkView.isMine)

035.        {

036.            if(GUI.Button (new Rect ((float)(0.5*Screen.width-60), (float)(Screen.height-60), 60, 60), skillTex1))

037.                {

038.            ShootBullet();}

039.

040.            if(GUI.Button(new Rect((float)0.5*Screen.width,(float)Screen.height-60,60,60),skillTex2))

041.            {

042.                ExplosiveEffect();

043.            }

044.        }

045.

046.    }

047.

048.    void OnCollisionEnter(Collision collisionInfo)

049.    {

050.

051.

052.        if(collisionInfo.gameObject.tag=="bullet" )

053.        {

054.            BulletScript bs = (BulletScript)collisionInfo.gameObject.GetComponent("BulletScript");

055.            if(bs.Owner != gameObject)

056.            {

057.                print("OnCollisionEnter"+collisionInfo.gameObject.name);

058.                Destroy(collisionInfo.gameObject);

059.

060.

061.                if(!networkView.isMine)

062.                    return;

063.                HeartControl.DecreaseLive();

064.            }

065.

066.

067.

068.        }

069.    }

070.

071.

072.

073.    void ExplosiveEffect()

074.    {

075.

076.        networkView.RPC("SpwanExplosion",RPCMode.All);

077.        SendMessage("PlayAnimation_Attack");

078.    }

079.

080.    void ShootBullet()

081.    {

082.        networkView.RPC("SpawnBullet",RPCMode.All);

083.    }

084.

085.    [RPC]

086.    void SpawnBullet ()

087.    {

088.

089.

090.        Vector3 forward = transform.TransformDirection (Vector3.forward);

091.        Transform effectPoint = transform.Find ("effectPoint");

092.        PrefabDepends preScript = (PrefabDepends)GameObject.Find("GameObject_GlobalController").GetComponent("PrefabDepends");

093.        if (effectPoint) {

094.

095.            Transform bullet = (Transform)Instantiate (preScript.bulletPrefab, effectPoint.position, Quaternion.identity);

096.            bullet.rigidbody.AddForce (forward * 2000);

097.            BulletScript bs = (BulletScript)bullet.GetComponent("BulletScript");

098.            bs.Owner = gameObject;

099.        }

100.

101.    }

102.

103.    [RPC]

104.    void SpwanExplosion()

105.    {

106.        Vector3 forward = transform.TransformDirection (Vector3.forward);

107.        Transform effectPoint = transform.Find ("effectPoint2");

108.        if (effectPoint) {

109.            //Object temp = Network.Instantiate (bulletPrefab, effectPoint.position, Quaternion.identity, 0);

110.

111.            Transform explosion = (Transform)Instantiate (explosionEffect, effectPoint.position, Quaternion.identity);

112.            //Network.Instantiate(bulletPrefab,transform.Find("effectPoint").position,Quaternion.identity,0);

113.        }

114.    }

115.

116.}

SpawnBullet就是调用的RPC call,在这里除了用子弹的prefab创建出子弹附加初始速度,还给子弹的脚本BulletScript的一个变量Owner赋值为脚本所附加到的玩家,这是为了判断这个子弹是哪个玩家发出用的。

碰撞检测的函数是OnCollisionEnter,要想触发这个函数,人物身上需要有一个Collider控件,而CharacterController是没有用的。所有的子弹都设为了名为"bullet"的tag,所以在这里检测,如果碰撞的对象是bullet,并且子弹上的脚本的变量Owner不是这个玩家自己,说明被别人的子弹击中,就先销毁本地创建出来的子弹,然后判断如果这个玩家是这个客户端所对应的,就进行减血。这个判断是必要的,因为这里的血量是全局静态的,只有一份代表自己,其他玩家被子弹攻击到了,不需要更新自己的血量。

2016-01-08 11:57:40 andyhebear 阅读数 1987
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

很多游戏玩家游戏死亡时一般都需要屏幕抖一下下或者屏幕变灰。为了在unity3d中实现这个特效,百度了下相关写法,发现方法很多~~~,找来找去,找到个简单粗暴地,啥都不需要,Camera Viewpoint实现 一个脚本拖动到Camera上就可以了,略微修改了一点点,share一下,下面是代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using UnityEngine;
using System.Collections;
 
public class ShakeCamera : MonoBehaviour
{
 
// 震动标志位
private bool isshakeCamera = false;
 
// 震动幅度
public float shakeLevel = 3f;
// 震动时间
public float setShakeTime = 0.2f;
// 震动的FPS
public float shakeFps = 45f;
 
private float fps;
private float shakeTime = 0.0f;
private float frameTime = 0.0f;
private float shakeDelta = 0.005f;
private Camera selfCamera;
 
void Awake()
{
selfCamera = GetComponent<Camera>();
}
 
// Use this for initialization
void Start()
{
shakeTime = setShakeTime;
fps = shakeFps;
frameTime = 0.03f;
shakeDelta = 0.005f;
}
 
// Update is called once per frame
void Update()
{
if (isshakeCamera)
{
if (shakeTime > 0)
{
shakeTime -= Time.deltaTime;
if (shakeTime <= 0)
{
selfCamera.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
isshakeCamera = false;
shakeTime = setShakeTime;
fps = shakeFps;
frameTime = 0.03f;
shakeDelta = 0.005f;
}
else
{
frameTime += Time.deltaTime;
 
if (frameTime > 1.0 / fps)
{
frameTime = 0;
selfCamera.rect = new Rect(shakeDelta * (-1.0f + shakeLevel * Random.value), shakeDelta * (-1.0f + shakeLevel * Random.value), 1.0f, 1.0f);
}
}
}
}
}
 
public void shake()
{
isshakeCamera = true;
}
}
 
  

好了本篇unity3d教程到此结束,下篇我们再会!

2018-05-25 15:06:23 SPU_HAO 阅读数 2240
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

关于2D游戏中游戏玩家的出生、无敌、死亡方法可以通过如下一个小实例详细讲解

我们小时候都玩过一款游戏——坦克大战

所以此实例为如何实现玩家坦克的出生、无敌、以及死亡方法


首先我们制作一个出生动画特效

(此动画特效本文章暂不做详细说明,如需了解请转至此文章学习了解

链接:https://blog.csdn.net/SPU_HAO/article/details/80452118)


新建脚本BORN1编写代码


注意:这两个延时调用Destroy延时销毁出生特效的时间必须要大于等于Invoke延时调用born方法的时间,否则并不会显示坦克

为什么?我们可以这么理解 


born方法里设置的位置为 当前出生特效的位置

而如果我们先执行Destroy销毁出生特效方法,再执行Invoke延时调用born方法,出生动画特效的位置已经被销毁了,born方法就找不到出生特效的位置,所以就不知道在哪里显示坦克

将BORN1脚本挂在我们一开始制作的出生特效的下边,同时将做好的坦克预制体挂上


运行  OK  我们可以看到我们挂的Player预制体在1f的出生动画特效后正确的显示出来(动图就不贴了)

之后我们来实现一下游戏玩家也就是我们坦克的无敌方法

首先添加一个引用 同时设定坦克的无敌时间以及无敌状态的判断

(此处涉及到无敌的预制体 也就是一个保护膜的动画,同出生动画特效,不做详解)


将方法放到类里


然后是死亡方法,类似


死亡方法很简单

Destroy(gameObject);销毁玩家即可

(如果有问题可以评论留言,看到后会回复)

注:所有文章为本人学习过程中记录的问题以及解决方案,是本人的学习过程笔记,以用于以后的知识回顾,同时供像我一样的初学者方便,有时涉及一些学习过程中记录的资料以及素材,如有所侵犯,请联系本人删除或修改,谢谢!

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