2015-09-14 13:12:44 tchenjiant 阅读数 2511
Unity2D技术
2D工程创建
这个选项并不是非常重要的,如果选择了2D项目,那么默认创建的摄像机就会变成了正交摄像机,而选择3D项目,默认摄像机会是透视摄像


机,需要手动修改。
修改默认设置,通过在Inspector选择Edit\Project Settings\Editor打开Editor Settings。
在Default Behavior Mode选项中,选择2D。
Scene View(场景视图)的2D模式
点击2D切换按钮启用2D模式:
贴图格式
Texture type,默认选择是Sprite类型,然后在类型的下面,有一个Sprite Mode选项,其中默认是Single单个图片的,Multiple是多个图片


。点击SpriteEditor,打开Sprite编辑窗口。
2D场景搭建
方法一:从Project视图中拖拽相应的Sprite到Hierarchy视图中或者场景视图中。
方法二:依次点击Gameobject->2DObject->Sprite,然后通过SpriteRender应用相对应Sprite贴图。
Sprite Renderer 精灵渲染器
Sprite:欲渲染的精灵对象。精灵对象的产生可以在“Texture importer”面板设置。
Color:该渲染网格的顶点颜色
Material:用来渲染精灵的材质球
Sorting Layer:用于精灵优先渲染的图层。
Order In Layer:精灵基于其设定层的优先级来渲染。值越小渲染顺序越靠前。
Rigidbody2D属性
Mass:0代表着无限大,也就是“静态刚体”。范围:0.001到100000。
Linear drag:线性阻尼,也就是物体在运动过程中收到的阻力。
Angular Drag:角度阻尼系数,刚体在旋转过程中受到的阻力。
Gravity Scale:重力缩放,控制着重力的大小,其数值范围为-100000到100000。
Fixed angle:固定角度,指刚体在运动过程中保持固定的角度,这就相当于关闭了刚体的选择功能。
Is Kinematic:关节,控制刚体是否变为运动学物体,就是我们的刚体不在受物理引擎的控制,而受Transform或者是动画等等的控制。
Sleeping Mode:睡眠,Unity会临时把处于静止状态的物理模拟去除,这样主要是节省计算资源。
Never Sleep :永远不睡眠。
Start Awake:awake时就进入睡眠。
Start Asleep:立即进入睡眠。
Collision Dectection:碰撞发现。
Discrete:正常状态下的检测。
Continuous:继续性检测。
2D碰撞器
Physics2D中碰撞器有以下四种类型:
BoxCollider2D:盒状碰撞器,一般为矩形; 
CircleCollider2D:圆形碰撞器;
EdgeCollider 2D:边缘碰撞器; 
PolygonCollider2D:多边形碰撞器;
2D碰撞器
Material:定义刚体表面的一些物理特性,例如摩擦力,柔软程度等,由此决定了它对其他物体的反弹能力等。
Is Trigger:属于3D碰撞的都应该知道这个属性的作用。勾了就会产生的是刚体碰撞。不勾就是触发碰撞,此时碰撞的两个物体之间可以不


使用刚体去进行驱动。


2D碰撞事件
Unity2D物理系统中,同样包含碰撞事件和触发事件。 
碰撞事件的检测方法:
OnCollisionEnter2D()方法:物体开始发生碰撞时,系统自动调用该方法。
OnColisionStay2D()方法:物体碰撞时在接触过程中,系统每帧都会调用该方法。
OnColisionExit2D()方法:物体碰撞结束或刚体停止触碰时,系统自动调用该方法。


2D触发事件
物体发生触发也是三种状态:进入触发,触发中,触发结束。相关的检测的系统方法如下:
OnTriggerEnter2D()方法:物体开始发生触发时,系统自动调用该方法。
OnTriggerStay2D()方法:物体触发时在接触的过程中,系统会每帧调用该方法。
OnTriggerExit2D()方法:物体触发结束或刚体停止触碰时,系统自动调用该方法。


UGUI介绍
Unity公司经过不断的测试,耗时约2年的时间终于推出了全新一代的UI系统。更灵活、更快速、更方便。


Unity4.6 全新UI 特点:
与Unity 引擎结合的更紧密。
     使用Unity 的Animation 与Animator 做uGUI 的动画系统。
 更加强大与易用的屏幕自适应。
简单理解:开发的手机游戏都能够自适应屏幕分辨率
 更加简单的UGUI 的深度处理机制。
在Canvas中,以父对象的上下循序,决定是否被“覆盖”的顺序,无需人工进行“层”的设定。
 完全自动化的图集打包机制。
NGUI是必须先打出图集然后做界面,还要考虑UI图集的分辨率。而UGUI完全不用考虑图集的概念。自动完成全新布局系统、强大与简单结合


的UI 控件、更容易的事件处理系统、2D 系统与 GUI 系统的完美耦合。


UI控件
uGUI自带了以下控件,其中Image用于显示Sprite,Raw Image用于显示Texture,Image Mask和Rect Mask用于clipping。所有控件都是


MonoBehaviour,可以直接从Inspector里拖到其它GameObject上。


Rect  Tool小工具
Rect Tool功能:改变控件的位置,改变大小,旋转。
提示:Rect Tool不单单专用于操作UI控件,实际上它可以被用于操作任何游戏对象。只不过这个工具是在UI系统加入的时候一并被添加进来


的。


Rect Transform
全新的布局系统:采用全新的Rect  Transform组件实现强大的UI布局。
Rect Transform继承自Transform,是uGUI最显著的特点。Empty GameObject加入一个UI Component时,Transform会自动转换为Rect 


Transform。


Anchors锚点
Anchor属性是重点,该用于表示UI控件的锚点,在Scene视图中使用4个小三角表示。锚点的4个小三角依次与UI控件四边形边框的四个角对应


,且在父对象的大小发生改变时,锚点会令子对象自动完成自适应操作。


Anchor Presets
Anchor Presets属性是一个“样子特殊的下拉列表”,此属性位于Rect Transform组件的左上角,单击鼠标正方形即可打开Anchor Presets


属性


Rect Transform
Pos (X, Y and Z)
相对锚点 anchors 的矩形枢轴 pivot 点的位置
Width/Height
矩形的宽高
Left, Top, Right, Bottom
矩形的边缘相对于其锚点的位置。这可以被认为是内部由锚点定义的矩形的填充。当锚点分离时 (见下文),将代


替 Pos 和 Width/Height 显示
Anchors Min/Anchors Max
作为父矩形的大小的一小部分定义的本矩形的右上角锚点。 0 , 0 对应于锚定到父级的左下角, 1 , 1 对应于锚定到父级的右


上角。
pivot
矩形旋转围绕着的点的位置 pivot 点,定义为本身的矩形的大小的几分之一为枢轴点的位置。 0 ,0 对应于左下角,而 1 ,1 对


应于右上角
Rotation
对象围绕其枢轴 pivot 点沿 X 、 Y 和 Z 轴的旋转角度
Scale
应用于该对象在 X 、 Y和 Z 的维度中的缩放比例


Canvas
首先在Hierarchy中创建画布(Canvas)
GameObject-->UI-->Canvas,或者创建其他的控件默认出现Canvas。Canvas 画布是摆放容纳所有的 UI 元素的区域。画布是一个游戏对


象上的某个Canvas component 组件,所有的 UI 元素必须是这个画布的子对象。
Canvas组件三种渲染方式。
Screen Space-overlay 此模式不需要UI摄像机,UI将永远出现在所有摄像机的最前面。
Screen Space-Camera此模式需要提供一个UICamera,它支持前方显示3D模型与粒子系统等。
World Space 这个就是完全3D的UI。


Canvas Scaler组件
属性UI  
Scale Mode:Constant Pixel Size:固定像素尺寸
Scale With Screen Size :以宽度为标准缩放(屏幕自适应特征)
    Screen  Match Mode:屏幕匹配模式
     1->Match Width Or Height 匹配宽度或高度
     2->Expand  扩展
     3->shrink 收缩
Scale Factor:控件缩放因子
Constant Physical Size:固定物理尺寸


Graphic Raycaster
每个Canvas都有一个Graphic Raycaster,用于获取用户选中的uGUI控件。多个Canvas之间通过设置Graphic Raycaster的priority来设置事


件响应的先后次序。当Canvas采用World Space或Camera Space时,Graphic Raycaster的Block选项可以用来设置遮挡目标


Event Systerm
EventSysterm控件具备三个组件,它是在创建Canvas控件的同时,系统自动添加的组件系统。
Event System
   事件系统组件
Standalone  Input Module
   独立输入模块
Touch Input Module
    触控输入模块


Panel控件
Panel为“面板”控件,主要功能就是一个“容器”。
通过Panel控件,可以更加合理与方便的整体移动与处理一组控件。
一个功能完备的UI界面,往往会使用多个Panel容器控件。
       Source Image 资源图像
       Color  颜色
       Material  材质球


Button控件
Interactable: 是否启用(具有交互作用)
Transition: 过渡方式, 改变颜色、更换贴图或自定义动画。
Color Tint 颜色色彩(默认状态)
Sprite Swap:精灵交互,需要使用相同的功能不同状态的贴图。
Animation:动画,最复杂,效果最绚丽
Button控件事件响应
在Button组件中有一个OnClick()选项,这就是Button控件处理事件的重要机制。
脚本中的导入命名空间:using UnityEngine.


Text控件
Font:字体
Font Style:  字体风格
Font Size:  字体尺寸
Line Spacing: 行间距
Rich  Text: 富文本
Paragraph:段落
Alignment:调整
Horizontal Overflow:水平溢出
Vertical  Overflow:竖直溢出
Best  Fit:最好匹配


Image控件
Images可以作为 uGUI 精灵导入,通过从TextureType选择设置Sprite (2D / uGUI)。uGUI用Image控件显示图片,图片就是一个Sprite.
Source Image:贴图资源
Color:贴图颜色
Preserve Aspect:图像的高度与宽度保持原始比例还是重新调整
Set Native Size:设置贴图原始大小


Raw lmage控件
Image组件需要一个精灵,但Raw Image需要的是纹理 (无边界等)。使用Raw Image是有必要,除非为图像会在大多数情况下适用。
Raw Image组件与Image组件类型,用于向玩家显示“不可交互”的图片信息,常作为游戏场景的装饰。但是这两个组件属性上并不完全一致



Texture:指定Raw Image组件要显示的图片。
提示 :Raw Image组件所显示的图片,可以是任何类型,而不单单只是Sprite类型。
UV RECT:令图片中的一部分显示在Raw Image组件里。X和Y属性指定图片左下角的位置,W和H属性指定图片右上角的位置。类似于裁剪。


Slider   滑动控件
滑块控件允许用户通过拖动鼠标从一个预先确定的范围选择一个数字值。熟悉的例子:包括在游戏中困难设置和在图像编辑器中亮度设置。


Scrollbar滚动条
滚动条控件允许用户滚动图像或其他太大的,可以完全看到的视图。请注意类似的滑块控件用于选择数字值,而不是滚动。熟悉的例子包括


在一个文本编辑器的一侧和垂直和水平两竖线用于查看较大的图像或地图的一个部分的垂直滚动条。


Input   Field输入文本控件
Input Field输入字段不是一个可见的 UI控件而是在以使TextControl控件的文本可编辑。
2016-02-12 19:44:51 WPAPA 阅读数 3139

最近用unity3d在写一个小功能时遇到的问题,就是在2D空间里,怎么让一个点注视另一个在空间里的点。
效果跟unity在3D空间里提供的一个方法叫 transform.LookAt(target); 类似。

lookat 有个挺不爽的地方,比如我想让一个点以插值移动的方式朝向另一个点,这个插值的角度没法控制,lookat会直接朝向那个点,就没插值的效果了,而且也无法判断出往哪个方向旋转最快。
然后发现了这个方法,贴出来给需要的小伙伴,造福大家 (ง •̀_•́)ง

图示:
这里写图片描述

代码:

public class Test : MonoBehaviour
{
    public Transform target;

    // Use this for initialization
    void Start()
    {
        // 世界坐标系转到本地坐标系
        Vector3 relative = transform.InverseTransformPoint(target.position);
        // 归一化(并不是必须的)
        relative.Normalize();

        // 反正切求弧并转成角度
        float angle = Mathf.Atan2(relative.x, relative.y) * Mathf.Rad2Deg;
        angle = Mathf.Abs(angle);

        // 左右2侧的垂直向量
        Vector3 leftVertical = new Vector3(-1, 0, 0);
        Vector3 rightVertical = new Vector3(1, 0, 0);
        // 跟目标向量做点积
        float leftDot = Vector3.Dot(relative, leftVertical);
        float rightDot = Vector3.Dot(relative, rightVertical);

        // >= 0 说明夹角 <= 90
        if (leftDot >= 0)
        {
            transform.Rotate(0, 0, angle);
        }
        else if (rightDot >= 0)
        {
            transform.Rotate(0, 0, -angle);
        }
        else
        {
            Debug.LogError("dot有问题");
        }
    }
}
2018-10-22 13:50:04 o0xiaoyin0o 阅读数 1171

最近刚开始看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();
    }
}

 

2017-12-20 17:42:14 unity_http 阅读数 1859

我是用daydream平台测试的,目前别的平台还没有测试

大概思路是playerSettings 中设置勾选Virtual Reality Supported 后选着对应的平台这里选的是Daydream 

然后在转换平台时用下面的方法加载到对应的平台,

UnityEngine.XR.XRSettings.LoadDeviceByName("None")

UnityEngine.XR.XRSettings.LoadDeviceByName("daydream");

并设置UnityEngine.XR.XRSettings.enabled = true;就可以切换到vr模式了


在同一个场景中增加两个MainCamera,


下面把脚本附上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.XR;


public class Manger3dTo2d : MonoBehaviour
{
    private bool is3d = true;


    public GameObject canvas;


    public GameObject mainCamare;


    public GameObject camare;


    //public GameObject evenSystem;


    public TextMesh tm;


    //public GameObject hand;
// Use this for initialization
void Start ()
{
    tm.text = XRSettings.loadedDeviceName;
    Debug.Log(XRSettings.loadedDeviceName + "333");
    is3d = true;
canvas.SetActive(false);
    camare.SetActive(false);
}

// Update is called once per frame
void Update () {
        if ((GvrControllerInput.AppButtonUp || Input.GetKeyUp(KeyCode.A)) && is3d)
    {
        canvas.SetActive(true);
        is3d = false;
            
        //UnityEngine.XR.XRSettings.enabled = false;
        XRSettings.LoadDeviceByName("None");
            Debug.Log(XRSettings.loadedDeviceName);
        tm.text = XRSettings.loadedDeviceName;
        //evenSystem.GetComponent<GvrPointerInputModule>().enabled = false;
        //evenSystem.GetComponent<StandaloneInputModule>().enabled = true;
            mainCamare.SetActive(false);
            camare.SetActive(true);
            //hand.SetActive(false);
    }
        if (GvrControllerInput.ClickButtonDown || Input.GetKeyUp(KeyCode.B))
        {
            To3d();
        }
}


    public void To3d()
    {        
        StartCoroutine(VrOn());    
    }


    IEnumerator VrOn()
    {
        XRSettings.LoadDeviceByName("daydream");
        Debug.Log(XRSettings.loadedDeviceName + "1111");
#if UNITY_EDITOR


#endif
#if UNITY_ANDROID
        yield return new WaitUntil(() => XRSettings.loadedDeviceName == "daydream");//到这一步pc不能测试了
#endif
        Debug.Log(XRSettings.loadedDeviceName + "222");
        yield return null;
        XRSettings.enabled = true;
        Debug.Log(XRSettings.loadedDeviceName);
        tm.text = XRSettings.loadedDeviceName;
        canvas.SetActive(false);
        is3d = true;
        mainCamare.SetActive(true);
        camare.SetActive(false);
        //hand.SetActive(true);
        //evenSystem.GetComponent<GvrPointerInputModule>().enabled = true;
        //evenSystem.GetComponent<StandaloneInputModule>().enabled = false;
    }


    public void ButtonClick()
    {
        Debug.Log("这是2d场景");
    }


}



2016-07-06 23:26:51 u010832643 阅读数 10666

引言

近日在开发项目中,遇到一个这样的需求:将炮弹旋转至开火方到受击方所成的角度上,简言之就是将一枚炮弹旋转到开或者到敌人的方向上。

如何旋转2D贴图?

查阅了很多资料,都是关于四元数,欧拉角的问题。有点杀鸡焉用牛刀的意味,于是自己摸索着利用已有的接口用一种简单的方法实现。(注意,我的需求存在于2D场景内)

用到的接口

Vector3.Angle

public static float Angle(Vector3 fromVector3 to);

Parameters

fromThe angle extends round from this vector.
toThe angle extends round to this vector.

Description

Returns the angle in degrees between from and to.

The angle returned is always the non reflex angle between the two vectors - ie the smaller of the two possible angles between them and never greater than 180 degrees.

using UnityEngine;

public class AngleExample : MonoBehaviour
{
	public Transform     target;

	// prints "close" if the z-axis of this transform looks
	// almost towards the target

	void Update ()
	{
		Vector3 targetDir = target.position - transform.position;
		float angle = Vector3.Angle( targetDir, transform.forward );

		if( angle < 5.0f )
			print( "close" );
	}
}

Vector3.Angle()代表的实际含义其实是,原点到from点与原点到to点的夹角,即OA与OB的夹角。俗话说不会美术的策划不是好程序:


然而当我们需要AB与水平坐标的夹角该怎么办呢?这时候就需要引入传说中的单位向量了。

解决方案

using UnityEngine;
using System.Collections;

public class ArrowTest : MonoBehaviour {

    public UISprite arrow;
	// Use this for initialization
	void Start () {
        TestForRotation(); 
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}

    void TestForRotation()
    {
        GameObject pointA = GameObject.Find("PointA");
        GameObject pointB = GameObject.Find("PointB");
        Vector3 vecA = pointA.GetComponent<Transform>().localPosition;
        Vector3 vecB = pointB.GetComponent<Transform>().localPosition;
        Vector3 direction = vecB - vecA;                                    ///< 终点减去起点
        float angle = Vector3.Angle(direction, Vector3.right);              ///< 计算旋转角度
        arrow.GetComponent<Transform>().Rotate(0, 0, angle);
    }
}
运行结果:

箭头指向AB方向,垂直结果:



任意“角度”运行结果:



为什么“角度”要加引号?我们来看如果需要旋转到BA所成的夹角会出现什么情况:


显然,箭头的指向于BA所成的角度并不一致。

这是由于Vector3.Angle()的定义中有这样一句话:The angle returned is always the non reflex angle between the two vectors - ie the smaller of the two possible angles between them and never greater than 180 degrees.

返回的角度总是两个角度中较小的一个,且不会超过180°,因此当所需旋转的角度大于90°时,需要进行适当的变换。如何界定是否超过90°呢?这时候Vector3.Dot,向量点乘就派上用场了,当旋转角度与Vector3.up相反时,需要对角度进行适当的变换。

修正后的代码如下:

using UnityEngine;
using System.Collections;

public class ArrowTest : MonoBehaviour {

    public UISprite arrow;
	// Use this for initialization
	void Start () {
        TestForRotation(); 
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}

    void TestForRotation()
    {
        GameObject pointA = GameObject.Find("PointA");
        GameObject pointB = GameObject.Find("PointB");
        Vector3 vecA = pointA.GetComponent<Transform>().localPosition;
        Vector3 vecB = pointB.GetComponent<Transform>().localPosition;
        //Vector3 direction = vecB - vecA;                                    ///< 终点减去起点(AB方向与X轴的夹角)
        Vector3 direction = vecA - vecB;                                  ///< (BA方向与X轴的夹角)
        float angle = Vector3.Angle(direction, Vector3.right);              ///< 计算旋转角度
        direction = Vector3.Normalize(direction);                           ///< 向量规范化
        float dot = Vector3.Dot(direction, Vector3.up);                  ///< 判断是否Vector3.right在同一方向
        if (dot < 0)
            angle = 360 - angle;
        Debug.LogWarning("vecA:" + vecA.ToString() + ", vecB:" + vecB.ToString() + ", angle: " + angle.ToString());
        arrow.GetComponent<Transform>().Rotate(0, 0, angle);
    }
}
箭头转向BA向量的结果如图:


7.11补充:

1)更新一种计算角度的方法,通过Atan()接口

2)通过欧拉角来旋转对象

3) 通过四元数的插值函数来平滑过渡旋转过程

using UnityEngine;
using System.Collections;

public class ArrowTest : MonoBehaviour
{

    public UISprite arrow;

    private Vector3 targetVec;
    private float targetAngle, AtanTarget;
    // Use this for initialization
    void Start()
    {
        TestForRotation();

    }

    // Update is called once per frame
    void Update()
    {
        ///< 补充点3: 通过插值使箭头平滑的转向指定的方向,在游戏中常用于人物转头,转移视角等操作,当然是在3D空间中,这里就抛块砖了。0.1f只是我偷懒写的一个单位值,正式的项目中一般会deltaTime * speed来控制转向的速度。
        arrow.GetComponent<Transform>().rotation = Quaternion.Slerp(arrow.GetComponent<Transform>().rotation, Quaternion.Euler(0, 0, AtanTarget), 0.1f);
    }

    void TestForRotation()
    {
        GameObject pointA = GameObject.Find("PointA");
        GameObject pointB = GameObject.Find("PointB");
        Vector3 vecA = pointA.GetComponent<Transform>().localPosition;
        Vector3 vecB = pointB.GetComponent<Transform>().localPosition;
        //Vector3 direction = vecB - vecA;                                    ///< 终点减去起点(AB方向与X轴的夹角)
        Vector3 direction = vecA - vecB;                                  ///< (BA方向与X轴的夹角)
        float angle = Vector3.Angle(direction, Vector3.right);              ///< 计算旋转角度
        direction = Vector3.Normalize(direction);                           ///< 向量规范化
        float dot = Vector3.Dot(direction, Vector3.up);                  ///< 判断是否Vector3.right在同一方向
        if (dot < 0)
            angle = 360 - angle;
        
        targetAngle = angle;
        targetVec = new Vector3(0, 0, angle);

        ///< 补充点1: 通过Atan2与方向向量的两条边可以计算出转向的角度,通过计算结果可以看到targetAngle与-AtanTarget相加正好是360°,即二者都指向同一方向。具体使用场景需要根据具体需求分析。
        AtanTarget = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        Debug.LogWarning("vecA:" + vecA.ToString() + ", vecB:" + vecB.ToString() + ", targetAngle: " + targetAngle.ToString() + ", AtanTarget: " + AtanTarget.ToString());
        //arrow.GetComponent<Transform>().Rotate(0, 0, angle);

        ///< 补充点2: 使用欧拉角来控制物体的旋转
        //arrow.GetComponent<Transform>().eulerAngles = new Vector3(0, 0, angle);
    }
}


开始学习unity3d游戏制作。

博文 来自: wuyt2008
没有更多推荐了,返回首页