Unity中雷达效果的制作

想给你游戏中增加个雷达么?Unity中可以很容易增加一个雷达.就像下面这样.当然.你可以让美术把雷达做的更好看一些.

将下面的脚本放在一个游戏对象上,给”blip”设置一个纹理.相当于雷达的信号效果.选择一个纹理作为雷达的背景(radarBG),设置地图在屏幕上的位置,设置一个游戏对象用于你雷达的centerObject(通常是目前的玩家对象).确保所有的”敌人”的标签tag都是”Enemy”.之后你就可以在你的游戏中看到雷达了.

两种语言任选其一.


@script ExecuteInEditMode()
// radar! by PsychicParrot, adapted from a Blitz3d script found in the public domain online somewhere ..

//Modified by Dastardly Banana to add radar size configuration, different colors for enemies in different states (patrolling or chasing), ability to move radar to either one of 9 preset locations or to custom location.

//some lines are particular to our AI script, you will need to change "EnemyAINew" to the name of your AI script, and change "isChasing" to the boolean within that AI script that is true when the enemy is active/can see the player/is chasing the player.

var blip : Texture; // texture to use when the enemy isn't chasing
var blipChasing : Texture; //When Chasing
var radarBG : Texture;

var centerObject : Transform;
var mapScale = 0.3;
var mapSizePercent = 15;

var checkAIscript : boolean = true;
var enemyTag = "Enemy";

enum radarLocationValues {topLeft, topCenter, topRight, middleLeft, middleCenter, middleRight, bottomLeft, bottomCenter, bottomRight, custom}
var radarLocation : radarLocationValues = radarLocationValues.bottomLeft;

private var mapWidth : float;
private var mapHeight : float;
private var mapCenter : Vector2;
var mapCenterCustom : Vector2;

function Start () {
    setMapLocation();  
}

function OnGUI () {
//  GUI.matrix = Matrix4x4.TRS (Vector3.zero, Quaternion.identity, Vector3(Screen.width / 600.0, Screen.height / 450.0, 1));

    // Draw player blip (centerObject)
    bX=centerObject.transform.position.x * mapScale;
    bY=centerObject.transform.position.z * mapScale;  
    GUI.DrawTexture(Rect(mapCenter.x - mapWidth/2,mapCenter.y-mapHeight/2,mapWidth,mapHeight),radarBG);
    
    // Draw blips for Enemies
    DrawBlipsForEnemies();
    
}
  
function drawBlip(go,aTexture){
    
    centerPos=centerObject.position;
    extPos=go.transform.position;
    
    // first we need to get the distance of the enemy from the player
    dist=Vector3.Distance(centerPos,extPos);
    
    dx=centerPos.x-extPos.x; // how far to the side of the player is the enemy?
    dz=centerPos.z-extPos.z; // how far in front or behind the player is the enemy?
    
    // what's the angle to turn to face the enemy - compensating for the player's turning?
    deltay=Mathf.Atan2(dx,dz)*Mathf.Rad2Deg - 270 - centerObject.eulerAngles.y;
    
    // just basic trigonometry to find the point x,y (enemy's location) given the angle deltay
    bX=dist*Mathf.Cos(deltay * Mathf.Deg2Rad);
    bY=dist*Mathf.Sin(deltay * Mathf.Deg2Rad);
    
    bX=bX*mapScale; // scales down the x-coordinate so that the plot stays within our radar
    bY=bY*mapScale; // scales down the y-coordinate so that the plot stays within our radar
    
    if(dist<=mapWidth*.5/mapScale){
        // this is the diameter of our largest radar circle
       GUI.DrawTexture(Rect(mapCenter.x+bX,mapCenter.y+bY,4,4),aTexture);

    }

}

function DrawBlipsForEnemies(){
    //You will need to replace isChasing with a variable from your AI script that is true when     the enemy is chasing the player, or doing watever you want it to be doing when it is red on    the radar.
    
    //You will need to replace "EnemyAINew with the name of your AI script
    
    // Find all game objects tagged Enemy
    var gos : GameObject[];
    gos = GameObject.FindGameObjectsWithTag(enemyTag);

    var distance = Mathf.Infinity;
    var position = transform.position;

    // Iterate through them and call drawBlip function
    for (var go : GameObject in gos)  {
          var blipChoice : Texture = blip;
          if(checkAIscript){
                var aiScript : EnemyAI = go.GetComponent("EnemyAI");
            if(aiScript.isChasing)
                    blipChoice = blipChasing;
        }
        drawBlip(go,blipChoice);
    }

}

function setMapLocation () {
    mapWidth = Screen.width*mapSizePercent/100.0;
    mapHeight = mapWidth;

    //sets mapCenter based on enum selection
    if(radarLocation == radarLocationValues.topLeft){
        mapCenter = Vector2(mapWidth/2, mapHeight/2);
    } else if(radarLocation == radarLocationValues.topCenter){
        mapCenter = Vector2(Screen.width/2, mapHeight/2);
    } else if(radarLocation == radarLocationValues.topRight){
        mapCenter = Vector2(Screen.width-mapWidth/2, mapHeight/2);
    } else if(radarLocation == radarLocationValues.middleLeft){
        mapCenter = Vector2(mapWidth/2, Screen.height/2);
    } else if(radarLocation == radarLocationValues.middleCenter){
        mapCenter = Vector2(Screen.width/2, Screen.height/2);
    } else if(radarLocation == radarLocationValues.middleRight){
        mapCenter = Vector2(Screen.width-mapWidth/2, Screen.height/2);
    } else if(radarLocation == radarLocationValues.bottomLeft){
        mapCenter = Vector2(mapWidth/2, Screen.height - mapHeight/2);
    } else if(radarLocation == radarLocationValues.bottomCenter){
        mapCenter = Vector2(Screen.width/2, Screen.height - mapHeight/2);
    } else if(radarLocation == radarLocationValues.bottomRight){
        mapCenter = Vector2(Screen.width-mapWidth/2, Screen.height - mapHeight/2);
    } else if(radarLocation == radarLocationValues.custom){
        mapCenter = mapCenterCustom;
    }
    
}

using UnityEngine;
using System.Collections;

public class Radar : MonoBehaviour
{

    public enum RadarTypes : int {Textured, Round, Transparent};
    public enum RadarLocations : int {TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, BottomRight, Left, Center, Right, Custom};
    
    // Display Location
    public RadarLocations radarLocation = RadarLocations.BottomCenter;
    public Vector2 radarLocationCustom;
    public RadarTypes radarType = RadarTypes.Round;
    public Color radarBackgroundA = new Color(255, 255, 0);
    public Color radarBackgroundB = new Color(0, 255, 255);
    public Texture2D radarTexture;
    public float radarSize = 0.20f;  // The amount of the screen the radar will use
    public float radarZoom = 0.60f;
    
    // Center Object information
    public bool   radarCenterActive;
    public Color  radarCenterColor = new Color(255, 255, 255);
    public string radarCenterTag;
    
    // Blip information
    public bool   radarBlip1Active;
    public Color  radarBlip1Color = new Color(0, 0, 255);
    public string radarBlip1Tag;

    public bool   radarBlip2Active;
    public Color  radarBlip2Color = new Color(0, 255, 0);
    public string radarBlip2Tag;

    public bool   radarBlip3Active;
    public Color  radarBlip3Color = new Color(255, 0, 0);
    public string radarBlip3Tag;

    public bool   radarBlip4Active;
    public Color  radarBlip4Color = new Color(255, 0, 255);
    public string radarBlip4Tag;
    
    // Internal vars
    private GameObject _centerObject;
    private int        _radarWidth;
    private int        _radarHeight;
    private Vector2    _radarCenter;
    private Texture2D  _radarCenterTexture;
    private Texture2D  _radarBlip1Texture;
    private Texture2D  _radarBlip2Texture;
    private Texture2D  _radarBlip3Texture;
    private Texture2D  _radarBlip4Texture;

    // Initialize the radar
    void Start ()
    {
        // Determine the size of the radar
        _radarWidth = (int)(Screen.width * radarSize);
        _radarHeight = _radarWidth;
        
        // Get the location of the radar
        setRadarLocation();

        // Create the blip textures
        _radarCenterTexture = new Texture2D(3, 3, TextureFormat.RGB24, false);
        _radarBlip1Texture = new Texture2D(3, 3, TextureFormat.RGB24, false);
        _radarBlip2Texture = new Texture2D(3, 3, TextureFormat.RGB24, false);
        _radarBlip3Texture = new Texture2D(3, 3, TextureFormat.RGB24, false);
        _radarBlip4Texture = new Texture2D(3, 3, TextureFormat.RGB24, false);
        
        CreateBlipTexture(_radarCenterTexture, radarCenterColor);
        CreateBlipTexture(_radarBlip1Texture, radarBlip1Color);
        CreateBlipTexture(_radarBlip2Texture, radarBlip2Color);
        CreateBlipTexture(_radarBlip3Texture, radarBlip3Color);
        CreateBlipTexture(_radarBlip4Texture, radarBlip4Color);
        
        // Setup the radar background texture
        if (radarType != RadarTypes.Textured)
        {
            radarTexture = new Texture2D(_radarWidth, _radarHeight, TextureFormat.RGB24, false);
            CreateRoundTexture(radarTexture, radarBackgroundA, radarBackgroundB);
        }
        
        // Get our center object
        GameObject[] gos;
        gos = GameObject.FindGameObjectsWithTag(radarCenterTag);
        _centerObject = gos[0];
    }
    
    // Update is called once per frame
    void OnGUI ()
    {
        GameObject[] gos;

        // Draw th radar background
        if (radarType != RadarTypes.Transparent)
        {
            Rect radarRect = new Rect(_radarCenter.x - _radarWidth / 2, _radarCenter.y - _radarHeight / 2, _radarWidth, _radarHeight);
            GUI.DrawTexture(radarRect, radarTexture);
        }

        // Draw blips
        if (radarBlip1Active)
        {
            // Find all game objects
            gos = GameObject.FindGameObjectsWithTag(radarBlip1Tag);
  
            // Iterate through them and call drawBlip function
            foreach (GameObject go in gos)
            {
                drawBlip(go, _radarBlip1Texture);
            }
        }
        if (radarBlip2Active)
        {
            gos = GameObject.FindGameObjectsWithTag(radarBlip2Tag);
  
            foreach (GameObject go in gos)
            {
                drawBlip(go, _radarBlip2Texture);
            }
        }
        if (radarBlip3Active)
        {
            gos = GameObject.FindGameObjectsWithTag(radarBlip3Tag);
  
            foreach (GameObject go in gos)
            {
                drawBlip(go, _radarBlip3Texture);
            }
        }
        if (radarBlip4Active)
        {
            gos = GameObject.FindGameObjectsWithTag(radarBlip4Tag);
  
            foreach (GameObject go in gos)
            {
                drawBlip(go, _radarBlip4Texture);
            }
        }

        // Draw center oject
        if (radarCenterActive)
        {
            Rect centerRect = new Rect(_radarCenter.x - 1.5f, _radarCenter.y - 1.5f, 3, 3);
            GUI.DrawTexture(centerRect, _radarCenterTexture);
        }
    }
    
    // Draw a blip for an object
    void drawBlip(GameObject go, Texture2D blipTexture)
    {
        if (_centerObject)
        {
            Vector3 centerPos = _centerObject.transform.position;
            Vector3 extPos = go.transform.position;
    
            // Get the distance to the object from the centerObject
            float dist = Vector3.Distance(centerPos, extPos);

            // Get the object's offset from the centerObject
            float bX = centerPos.x - extPos.x;
            float bY = centerPos.z - extPos.z;
    
            // Scale the objects position to fit within the radar
            bX = bX * radarZoom;
            bY = bY * radarZoom;
    
            // For a round radar, make sure we are within the circle
            if(dist <= (_radarWidth - 2) * 0.5 / radarZoom)
            {
                Rect clipRect = new Rect(_radarCenter.x - bX - 1.5f, _radarCenter.y + bY - 1.5f, 3, 3);
                GUI.DrawTexture(clipRect, blipTexture);
            }
        }
    }

    // Create the blip textures
    void CreateBlipTexture(Texture2D tex, Color c)
    {
        Color[] cols = {c, c, c, c, c, c, c, c, c};
        tex.SetPixels(cols, 0);
        tex.Apply();
    }
    
    // Create a round bullseye texture
    void CreateRoundTexture(Texture2D tex, Color a, Color b)
    {
        Color c = new Color(0, 0, 0);
        int size = (int)((_radarWidth / 2) / 4);
        
        // Clear the texture
        for (int x = 0; x < _radarWidth; x++)
        {
            for (int y = 0; y < _radarWidth; y++)
            {
                tex.SetPixel(x, y, c);
            }
        }
        
        for (int r = 4; r > 0; r--)
        {
            if (r % 2 == 0)
            {
                c = a;
            }
            else
            {
                c = b;
            }
            DrawFilledCircle(tex, (int)(_radarWidth / 2), (int)(_radarHeight / 2), (r * size), c);
        }
        
        tex.Apply();
    }
    
    // Draw a filled colored circle onto a texture
    void DrawFilledCircle(Texture2D tex, int cx, int cy, int r, Color c)
    {
        for (int x = -r; x < r ; x++)
        {
            int height = (int)Mathf.Sqrt(r * r - x * x);

            for (int y = -height; y < height; y++)
                tex.SetPixel(x + cx, y + cy, c);
        }
    }

    // Figure out where to put the radar
    void setRadarLocation()
    {
        // Sets radarCenter based on enum selection
        if(radarLocation == RadarLocations.TopLeft)
        {
            _radarCenter = new Vector2(_radarWidth / 2, _radarHeight / 2);
        }
        else if(radarLocation == RadarLocations.TopCenter)
        {
            _radarCenter = new Vector2(Screen.width / 2, _radarHeight / 2);
        }
        else if(radarLocation == RadarLocations.TopRight)
        {
            _radarCenter = new Vector2(Screen.width - _radarWidth / 2, _radarHeight / 2);
        }
        else if(radarLocation == RadarLocations.Left)
        {
            _radarCenter = new Vector2(_radarWidth / 2, Screen.height / 2);
        }
        else if(radarLocation == RadarLocations.Center)
        {
            _radarCenter = new Vector2(Screen.width / 2, Screen.height / 2);
        }
        else if(radarLocation == RadarLocations.Right)
        {
            _radarCenter = new Vector2(Screen.width - _radarWidth / 2, Screen.height / 2);
        }
        else if(radarLocation == RadarLocations.BottomLeft)
        {
            _radarCenter = new Vector2(_radarWidth / 2, Screen.height - _radarHeight / 2);
        }
        else if(radarLocation == RadarLocations.BottomCenter)
        {
            _radarCenter = new Vector2(Screen.width / 2, Screen.height - _radarHeight / 2);
        }
            else if(radarLocation == RadarLocations.BottomRight)
        {
            _radarCenter = new Vector2(Screen.width - _radarWidth / 2, Screen.height - _radarHeight / 2);
        }
            else if(radarLocation == RadarLocations.Custom)
        {
            _radarCenter = radarLocationCustom;
        }
    }

    
}

Unity iPhone 1.7版发布,支持iPad!!

写在前面,如果你个人不喜欢iPad,觉得是放大版iTouch,那么请不要把你个人想法意见施加与所有人.每个人每个物存在都有它的原因.
I don’t know why i need this,but i got to get one.

亮点
Unity iPhone 基础版和Unity iPhone高级版都支持iPad的开发.
如果你还没有iPad硬件设备,你仍旧可以开发iPad,因为现在支持iPad模拟器了.
添加universal application支持,你的程序能工作于iPhone和iPad.

附加功能和改进
在Player设置中可以选择iPad target,设置图标和启动画面等等.
3:4和4:3比例用于iPad游戏开发.

错误修正
iPhone基础版可以用System.xml了.
静态物体整合(static batching)现在能正确处理多材质的模型了.

已知问题
Unity iPhone Remote还不能工作于iPad.
在Unity iPhone编辑器中Unity iPhone Remote还不支持iPad的分辨率模拟.
视频播放只能以”portrait”方式在iPad上播放(临时解决办法你可以将视频进行旋转).
音频播放器在iPad模拟器上有问题(很有可能是iPad模拟器的Bug).
Xcode中显示很多无关紧要的警告.

iPhone的Push(推送通知)功能原理浅析

iPhone QQ发布了3.3.0,主要增加了对iPhone Push功能的支持。但是,由于blacksn0w解锁软件的缺陷,用其解锁激活的iPhone无不出现了Push的缺陷。鉴于国内许多人对iPhone的Push功能的误解,并导致很多匪夷所思的言论,晓晓决定写一篇文章,对iPhone的Push功能,进行一次科普,顺便为各位分析下目前存在的几种补丁的原理。
敬告小白:本文理论内容来自iPhone官方参考文件,涉及破解的内容来自dev team和ih8sn0w。如果你认为你对iPhone的理解比Apple还要正确,请直接向Apple指出文档中的错误之处。本人无责任翻译概括。
注意:blackra1n越狱本身并不会导致不能Push的缺陷,导致缺陷的是用于解锁的blacksn0w。如果你想争论,请先阅读完本篇文章,再自己好好想想。
第一部分:Push原理
(以下绝大多数内容参考自、图片来自iPhone OS Reference Library)
机制简介
Push的工作机制可以简单的概括为下图

图中,
Provider是指某个iPhone软件的Push服务器。
APNS是Apple Push Notification Service(Apple Push服务器)的缩写,下文统一使用该缩写。
因此,整个过程可以分为三个阶段,下面用大家常用的聊天客户端BeejiveIM来说明。(BeejiveIM是一款支持多账户登录的支持Push的iPhone聊天客户端,支持MSN、Google Talk等)
此时Provider为BeejiveIM服务器,我们在BeejiveIM上登陆MSN,其实软件是先把登录信息发送到BeejiveIM服务器,再通过其服务器来登陆MSN。因此,当我关闭了BeejiveIM,BeejiveIM服务器会继续为我登陆MSN,此时如果有人对我的MSN账户发送了消息,那么就会触发Push。此时:
第一阶段:BeejiveIM服务器把要发送的消息、目的iPhone的标识打包,发给APNS。
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
Push认证
许多朋友说Push不能用。其中一大部分,就是在认证阶段就出了问题。想了解原因?请细看:
这里所说的认证机制,实际上包含两层。一层是物理连接上的认证,另一层则才是涉及到iPhone设备令牌的认证。
物理连接上的认证:SSL/TLS链接

(如果你了解TLS,那么这里我几乎无需介绍。)
iPhone在开启Push的时候,会连接APNS建立一条TLS加密链接。每一台正常的iPhone都有一个独有的设备证书,而APNS也有一个服务器证书。两者建立的时候,会验证彼此的证书有效性。
TLS链接一旦建立,在没有数据的情况下,只需要每隔15分钟进行一次保活的握手,因此几乎不占流量。而一旦因为意外原因导致链接中断,iPhone会不断重新尝试建立TLS链接,直到成功。
更高一层次:基于token(令牌)的认证
在机制简介里,我提到过APNS判断Push推送消息该发给哪台iPhone的依据是一个“目的iPhone的标识”,这个标识就是device token(设备令牌)
设备令牌是怎么生成的呢?是每次建立TLS连接时,APNS通过前一层次(TLS层)里我们提到的每台正常的iPhone唯一的设备证书(unique device certificate),并用令牌密钥(token key)加密生成的。

在令牌生成了之后,APNS会把设备令牌(device token)返回给iPhone,而对应的Push应用程序(如BeejiveIM),则把返回来的设备令牌(device token)直接发送给Provider(如BeejiveIM服务器)。这样,当Provider有Push消息要发送时,就会把对应帐号的设备令牌(device token)和消息一起发送给APNS,而APNS再依据设备令牌(device token),找到相应TLS链接的iPhone,并发送相应的Push消息
以上复杂的流程可以归纳为下面这幅图:

图中,Client App是iPhone上的Push应用程序。(图中缺了一条(当有Push消息时)由Provider到APNS的链接)
最重要的部分——每台iPhone独有的设备证书和密钥的来历
正常的iPhone刷系统之后,是没有设备证书和密钥的。这就是为什么iPhone会需要连接到iTunes上进行激活——激活过程中,Apple会分配给每台iPhone独一无二的设备证书(device certificate)和密钥(key)
以上我仅仅介绍了从iPhone到APNS的链接建立。其实从Provider到APNS也有一条TLS链接,但是与本文关系不大,所以不多加介绍了。
我的PUSH问题出在哪里?
相信许多同学都抱有这样的疑问。
正如上文提到的,iPhone的Push需要APNS生成对应iPhone的设备令牌,但生成这个令牌又需要iPhone上的有效的设备证书(device certificate)和密钥(key),但是:
iPhone OS 3.X 使用blacksn0w进行解锁的过程,是不经过iTunes的,而blacksn0w本身又不生成对应的设备证书(device certificate)和密钥(key),因此这样解锁完的iPhone根本不可能与APNS建立任何的TLS链接,Push自然废了。
有关各种pushfix补丁
要修补这个问题,唯一的办法就是重新生成唯一且有效的设备证书(device certificate)和密钥(key)
但是要知道,证书是需要机构签发的,自己一个人随便弄的一个证书,只会被APNS认为是无效证书。(SSL证书一个多少钱大家可以去查查)
并且对应的文件似乎还和iPhone本机的一些内容相关,不是直接制作好的文件放进去就可以的。
于是,最早,dev team推出了一个测试版补丁,Push fix by dev team(通过他们的twitter发布的,因此官网没有消息)。这个补丁初期很有效。但是仅在iPhone 2G上比较正常。
之后某人士发布pushfix 1.0了。由于使用了不同的生成方法,因此在新版本iPhone上也正常工作了。于是风靡一时。
然而,以上两个补丁都有严重的隐患——他们使用了一个固定的证书作为设备证书(device certificate)。因此在不同iPhone上的区别仅仅在于生成的密钥(key)不同。(待确认)
上面提到过,APNS依靠每台iPhone独一无二的设备证书(device certificate)和密钥(key)来生成独一无二的设备令牌(device token),用来标识每台iPhone。
但当多个iPhone的设备证书(device certificate)完全一致时,就存在一定几率使得多个iPhone获得相同的设备令牌(device token)
而随着这两个补丁的使用人数不断增加,使得出现获得相同设备令牌(device token)的iPhone数量大大增加了。
当这些相同设备令牌(device token)的iPhone上启用了同一个应用程序的Push的时候,就极有可能出现彼此间的Push串发的现象。——如某论坛目前N多人抱怨QQ的Push到别人iPhone上的情况就是如此。
之后,Pushfix的作者,声称自己可以为每台iPhone手工制作唯一的设备证书(device certificate)和密钥(key),并且开始提供了付费服务,并且最终推出了付费的Pushfix 2.0——其通过cydia安装的原理是,在安装的时候在线连接到pushfix站点检查对应iPhone的imei确定是否付费再自动下载对应的证书。
虽然不知道他是怎么制作这些证书的。但是经过晓晓的验证,他制作的证书确实是有效的。Push问题确实修复了。
在这之后,某论坛上出现了一个叫做Pushfix_D的补丁,声称无需付费也能直接修复问题。然而,
——考虑到一些情况,我决定把对Pushfix_D的判断用英文发出来。当然,制作者肯定很清楚下面写的东西:)
it contains the same released push keys from back in July 2009.  Everybody gets the same key, so it is going to have all the same problems of ALL the free push fixes.  Push isn’t going to work very long and it is going to drain your battery.
其他出错的情况
我的iPhone在cmwap下无法push?!
对的,这完全正常。在wap网内,TLS链接几乎无法建立成功。
我的iPhone在Wi-Fi下无法push?!
实际上这得说是iPhone与某些无线路由器的不兼容。如果无线路由器开启了DNS转发功能,那么很有可能你的iPhone无法成功与APNS服务器建立TLS链接。
解决方法:
关闭无线路由器的DNS转发功能,手动为iPhone的Wi-Fi连接设置DNS为8.8.8.8
补充,实际上,这也就是为什么iPhone连接到Wi-Fi上而又不能收到Push的时候,会变得发热且非常耗电。因为iPhone会不断尝试建立TLS链接
如何得知我的Push是否破解成功?
一个简单的方法就是安装 Twitbird Pro版本。在其Accounts页面,会显示当前软件的Push注册状况。
或者你可以用WinSCP之类的软件查看iPhone上的
/var/mobile/Library/Preferences/com.apple.apsd.plist
文件状态。
如果其大小为119字节,则说明该iPhone已经成功取得了设备令牌(device token),并保存在该文件中。
如果小于该大小,则说明该iPhone已经和APNS链接过,但是未能取得设备令牌(device token)。
如果没有该文件,那说明该iPhone根本没能成功连接到APNS。
其他一些值得注意的问题
iPod Touch与iPhone的Push机制不完全相同,锁屏后15分钟方检查一次。故请勿与上文对号入座。
APNS在发送Push消息时,如果发现对应的iPhone链接中断,则会延后几分钟再发送。超过一个时间后,Push消息会被删除。因此请注意你的网络状况是否影响Push正常工作。
如上文所说,每台iPhone的设备令牌(device token)储存在/var/mobile/Library/Preferences/com.apple.apsd.plist 文件中。这就是为什么每次需要重装Push补丁时,建议删除push程序并删除该文件。
使用sbsettings的EDGE开关关闭EDGE,却不关闭Push的话,会导致iPhone不断尝试建立TLS连接,最终耗尽电量。因此,如果你不打算或不能用Push,请关闭Push选项。
对软件的Push服务器(Provider)而言,Wi-Fi与手机网络是一样的,在Push处理上不会有任何区别。
虽然已经解释的很清楚,但还是明说一句,只要TLS连接正常,Push服务就是实时的,速度仅取决于Provider而已。
题外话,iPhone上的邮件推送为Push Mail技术,与本文所说的Push完全不同。请查阅Exchange Direct Push相关内容。
福利
一句话,如果你觉得Push没什么用,那只能说明你见识太少。在以下页面可以查看一些支持Push的优秀软件。
http://appadvice.com/applists/show/definitive-list-of-push-capable-apps
内容参考:iPhone OS Reference Library

转自:http://xiaolife.com/wordpress/an-introduce-to-iphone-push/