照相机拍照片怎么和unity3d 人物模型中模型相匹配

【Unity3D】2D飞机大战游戏完整制作(含项目资源、适合新手)
*********************************************************
**游戏项目资源下载链接: &
**If you want to download more resources, please
share your resources!
1,主摄像机的设置
将3D设置成2D:
将照相机的Position、Rotation都复位
2,飞机模型显示在照相机内
拖动sprite预制物体到监视面板,然后将飞机模型的图片添加上去
照相机的位置:
飞机的位置:
3,控制飞机上下左右移动
//控制飞机左右移动(默认左右键和AD键),Horizontal表示水平轴
transform.Translate(Input.GetAxis("Horizontal")*Time.deltaTime,0,0);
//控制飞机上下移动(默认上下键和WS键),Vertical表示垂直方向
transform.Translate(0,Input.GetAxis("Vertical")*Time.deltaTime,0);
4,控制飞机循环移动
判断好边界值就行
5,发射炮弹(撞击物体消失、飞到屏幕外面消失)
炮弹大少调节:
第一种发射:
1)炮弹的发射与销毁
发射:transform.Translate(0, speed * Time.deltaTime,
销毁: Destroy(gameObject,
2);2)将炮弹GameObject变成预制物体
3)在飞机的Controller.js移动脚本中实例化炮弹(通过空格发射)
if(Input.GetKeyDown(KeyCode.Space))
Instantiate(paodan,transform.position,transform.rotation);
第二种发射:
1)只需要将销毁脚本添加给炮弹,变成预制物体
2)在飞机上附一个脚本,实现炮弹的发射以及炮弹的实例化
var&n:Rigidbody=Instantiate(newobject,transform.position,transform.rotation);
n.velocity=transform.forward*30.0;
6,陨石的参数设置
7,太空背景动态移动
第一张设置
第二张设置
两张背景赋同一个循环脚本
var&speed:float=1.0;
function&Update&()&
if(transform.position.y&-3.9)
transform.position=new&Vector3(0,8,1);
//当陨石小于y轴的-4(坠落在屏幕下方时),再在上面重新new一个背景图出来
transform.Translate(0,-speed*Time.deltaTime,0);
解决循环过程中无缝链接的问题:
将主相机的调成黑色
8,碰撞(要将所有的的物体放在z轴的同一位置)
给炮弹添加碰撞体
2)给怕炮弹添加刚体
给炮弹添加标签
最后将炮弹拖到预制物体的炮弹中,让其替换掉以前的炮弹预制
飞机和陨石同样的设置
9,陨石与炮弹碰撞
思路:碰撞时,让陨石new在新的位置处(不用销毁次物体),而炮弹销毁掉
function&OnTriggerEnter(other:Collider)&
if(other.tag=="projectile")
//将陨石new在新的位置
transform.position=new&Vector3(Random.Range(-2.5,2.5),3.5,0);
Destroy(other.gameObject);
10,爆炸效果(陨石与炮弹、陨石与飞机)、Animation动画脚本
爆炸图片的属性(图片水平方向是由7个爆炸组成的)
Tiling:平铺;Offset:偏移
最开始是:表示显示全部
设置成这样
水平方向上:七张图片
七个爆炸中的每一个爆炸效果都是1/7=0.143
Tiling.x=0.143,Offset.x=0表示第一个爆炸效果
Tiling.x=0.143,Offset.x=0.143表示第二个爆炸效果
..............
垂直方向上:分成两部分
Tiling.y=0.5,Offse.y=0表示图片的下半部分
Tiling.y=0.5,Offse.y=0.5表示图片的上半部分
将爆炸效果存放在预制物体中
在陨石碰撞函数实例化预制物体中爆炸效果
11,发射多枚子弹
2D平面沿这z轴旋转角度即可
实现代码:
z=Instantiate(paodan,transform.position,transform.rotation);
y=Instantiate(paodan,transform.position,transform.rotation);
z.transform.Rotate(0,0,30);//斜角发射炮弹
y.transform.Rotate(0,0,-30);
12,实现计分功能和生命值
血条:利用GUI.Box绘制
&(自己动手丰衣足食)
13,倒计时功能
var&timeNumbers:Texture[];//图片
static&var&leftTime:int=100;//100s
var&myTime:float=0;//计时
function&Update&()&
myTime+=Time.deltaT
if(myTime&1)
leftTime--;
if(leftTime&1.0)
leftTime=0;
function&OnGUI()
for(var&i:int=0;i
GUI.DrawTexture(new&Rect(350+i*32,20,32,45),
timeNumbers[System.Int32.Parse((leftTime.ToString())[i].ToString())]);
//leftTime.ToString().Length表示取数字的长度(百位数的长度为3,10-99的长度为2)
//GUI.DrawTexture显示一张图片的命令
//Rect(350+i*32,20,32,45)图片显示的位置(x,y,w,h)
//System.Int32.Parse()字符串转整数型
14,新的场景的搭建(开始)
通过start.js脚本,不需要添加GUIText和加入图片,在脚本中用到GUI.DrawTexture()函数创建图片,并让其显示在整个屏幕中。GUI.Label创建标签(提示信息)。Rect()表示创建的位置
private&var&intext:String="Instruction:\n\n&Press&left&and&Right&arrow&To&Move&.\n&Press&Space&to&fire.";//创建提示信息
var&startTexture:T//图片
function&OnGUI()
//绘制一个矩形,即为图片的位置
GUI.DrawTexture(new&Rect(0,0,Screen.width,Screen.height),startTexture);
//标签的位置
GUI.Label(new&Rect(10,10,250,200),intext);
//按任意键开始
if(Input.anyKeyDown)
//加载场景
Application.LoadLevel("youxi");
15,场景调用
由其它场景加载游戏这个场景的时候,一些(静态)变量要重新赋初始值
1)飞机生命值为0的时候调用失败场景
没有调用失败场景,感觉出来的时候太突然,所有用的一个restart.js脚本实现死亡后的界面
2)倒计时为0后,调用赢家场景
【福利】,图片处理(PS)
1,先在图层处进行解锁双击点击确定即可解锁
2,,选取工具
3,选取完后,在图像大少中将图片设置成64X64的,保存为png格式
16,随机产生图片
&renderer.material.mainTexture=yunshi[Mathf.RoundToInt(Random.Range(0.0,4.0))];
17,本地保存最高分与姓名
当玩家死亡的时候,判断得多少分
PlayerPrefs.GetInt("highscore")获取本地注册表的数据
PlayerPrefs.SetInt("highscore",defen);存数据在本地
xm&=&GUI.TextField&(Rect&(250,&200,&200,&20),&xm,&25);//字符输入框,字符限制25字节
PlayerPrefs.SetString("sir",xm);//将名字存在注册表中
18,添加敌机和敌机发射的子弹
,子弹制作和前面的一样,除了实现发射功能和超出屏幕下方销毁之外,还要添加与飞机碰撞与飞机发射的子弹碰撞的功能
敌机&要实现的是,让它左右自动移动,并且能发射子弹,(倒计时5s后,才出现敌机)
diji.SetActive(true);激活物体的函数
19,添加医疗包
,当医疗包与飞机碰撞时,让其隐藏并且重新生成在屏幕的上方。
,当医疗包超出屏幕下方时,也让其重新生成在屏幕商法,并隐藏起来
值得注意的是,这里不能用实例化,因为在时间相等一刻实例化会产生很多医疗包
**************************************************************************************************
以上所以步骤基本上可以完成一个简单的2D飞机大战,所谓"师傅引进门,修行靠个人"(-,-
&博主也学不久),想要做的更好那就靠你自己了,学习unity的童鞋们,加油吧!!!
所有不懂,请私密我
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。手机门户>>
热门点击>>
手机腾讯>>
电脑上wap网:Unity3D 用触摸和鼠标输入缩放相机_达内Unity3D培训
Unity3D 用触摸和鼠标输入缩放相机_达内Unity3D培训
400-111-8989
Unity3D 用触摸和鼠标输入缩放相机
当为Github Game Off 2016开发Byter时,我想允许玩家用触摸(点击或拖动来缩小,手指捏放来放大)设备包括及iOS,以及用桌面上的鼠标(点击和拖动来缩小,鼠标滚轮来放大)及游戏的WebGL版本来缩放照相机。 Byter的照相机有固定的角度,意味着玩家不能旋转,但对于在游戏中收集丢失的数据包来说,放大缩小很重要。相机的放大缩小对于大多数地静态点击风格游戏的交互来说也是意外的惊喜。源码在开源库中 /KyleBanks/ggo16-byter已经可用,普遍的版本在博客底部已经提供了,但我想它可能对别的Unity开发者有用,因此我喜欢通过代码来解释它是怎么运作的。照相机设置 照相机安装很标准,我简单用固定角度的透视投影(这个对于我们处理放大很重要)来给一个稍微倾斜的视野。显著的唯一的一件事是CameraHandler脚本附加于照相机上,这个脚本是通过输入处理来控制放大缩小的。脚本 下面的代码包含了CameraHandler脚本,没必要在课程外使用逻辑学,除非你想个性化。必需变量 我做的第一件事是定义缩放的边界,照相机移动和放大的速度。这让我限制照相机到场景固定的区域中,并限制我们能放大照相机多少。依据你的游戏和欲望,这些变量会不同,下面是我定义它们的方式:private static readonly float PanSpeed = 20f;private static readonly float ZoomSpeedTouch = 0.1f;private static readonly float ZoomSpeedMouse = 0.5f;private static readonly float[] BoundsX = new float[]{-10f, 5f};private static readonly float[] BoundsZ = new float[]{-18f, -4f};private static readonly float[] ZoomBounds = new float[]{10f, 85f};边界被定义为浮点数组,每个的长度为2。第一个值代表边界的下限,第二个代表边界的上限。比如这个例子中的BoundsX,我保持照相机在X轴上的-10到5之间。简单而言,BoundsZ会控制Z轴,ZoomBounds用于放大。对Byter来说没有y轴上的移动,因此也没有必要为它定义边界。接下来,我们需要一些示例变量来追踪帧之间的照相机状态。我们想要保持实际照相机的参照物,因此我们可以修改属性为用户的交互:private Cprivate Vector3 lastPanPprivate int panFingerId; // Touch mode onlyprivate bool wasZoomingLastF // Touch mode onlyprivate Vector2[] lastZoomP // Touch mode only我们一个一个来分析这些属性:cam存储照相机的参照物。lastPanPosition是最后一帧之间用户缩小照相机的地方时,用户的手指或鼠标位置。panFingerid跟踪手指的ID用来缩小照相机,仅仅用触摸模式。不能全部都用鼠标来控制,因为只有一个鼠标可以用。wasZoomingLastFrame用触摸模式来决定照相机是否在最后一帧被放大。lastZoomPositions,像lastPanPosition,追踪用户手指在最后一帧之间他们放大照相机的的位置。这个属性,不像lastPanPosition,仅仅是触摸模式可用,不能用鼠标控制。唤醒(Awake) 我们用唤醒(Awake)函数,在这个函数中我们获取到照相机的参照物void Awake() {cam = GetComponent();}如果你之前用过unity就会觉得熟悉,我们仅仅是获取GameObject的Camera组件。你用cam=Camera.main来替换,但我选择用GetComponent你添加另一个照相机到你的游戏或从你的照相机移除MainCamera。以防万一,这是我们在Awake函数所需要的,我们准备写实际的逻辑。更新(Update) 在更新循环中我们需要检查我们是否需要处理触摸或鼠标控制,我们定义两个空的函数(到目前为止),y以便在任何一个例子中可以调用:void Update() {if (Input.touchSupported && Application.platform != RuntimePlatform.WebGLPlayer) {HandleTouch();} else {HandleMouse();}}void HandleTouch() {}void HandleMouse() {}我的目的,我简单检测下触摸是否用Input.touchSupported属性来支持,并确保游戏在webGl播放器中运行。这个很重要因为WebGL播放器支持触摸,但因为手机现在不能用webgl来支持Unity。我假设所有的webgl播放器在桌面浏览器中播放而不在手机上播放。当菜单打开的时候,我想阻止照相机放大缩小,对于Byter来说也没什么,因此在Update函数的顶部来检查平台并调用Handle_函数,比如这样:// OPTIONALif (isMenuOpen) {}这是完全选择性的,你也许对游戏有你的想法,你不想让照相机移动,所以如果这样的话,update函数的顶部是一个好地方来确认你是否处于照相机交互的状态。处理鼠标 对了,是时候做些移动了。我们将拓展HandleMouse函数,更容易测试(Unity编辑器会用这个)很容易扩展触摸控制器。void HandleMouse() {// On mouse down, capture it's position.// Otherwise, if the mouse is still down, pan the camera.if (Input.GetMouseButtonDown(0)) {lastPanPosition = Input.mouseP} else if (Input.GetMouseButton(0)) {PanCamera(Input.mousePosition);}// Check for scrolling to zoom the camerafloat scroll = Input.GetAxis("Mouse ScrollWheel");ZoomCamera(scroll, ZoomSpeedMouse);}首先我们检测鼠标是否用Input.GetMouseButtonDown点击这一帧并简单存储目前鼠标的位置作为LastPanPosition.如果鼠标不点击这帧,我们检测是否用Input.GetMouseBotton来点击并执行PanCamera方法。接下来,我们用滚轮来处理放大。用Input.GetAxis并提供“Mouse ScroollWheel”做轴,我们得到距离,滚轮从最后一帧滚动。接下来我们用从Input.GetAxis输入返回的scroll来调用ZoomCameray并达到我们想放大的速度。这儿我用以上定义的ZoomSpeedMouse内容,你可能猜到我们用ZoomSpeedTouch常量。放大缩小照相机 我们进入触摸输入前,我们拓展下PanCamera和ZoomCamera函数。这些都不是特别复杂,我们看下:void PanCamera(Vector3 newPanPosition) {// Determine how much to move the cameraVector3 offset = cam.ScreenToViewportPoint(lastPanPosition - ewPanPosition);Vector3 move = new Vector3(offset.x * PanSpeed, 0, offset.y * PanSpeed);// Perform the movementtransform.Translate(move, Space.World);// Ensure the camera remains within bounds.Vector3 pos = transform.pos.x = Mathf.Clamp(transform.position.x, BoundsX[0], BoundsX[1]);pos.z = Mathf.Clamp(transform.position.z, BoundsZ[0], BoundsZ[1]);transform.position =// Cache the positionlastPanPosition = newPanP}void ZoomCamera(float offset, float speed) {if (offset == 0) {}cam.fieldOfView = Mathf.Clamp(cam.fieldOfView - (offset * speed), ZoomBounds[0], ZoomBounds[1]);}PanCamera获得鼠标(或手指)新的位置并创建一个基于之前的鼠标(或手指)的位置偏移量(offset)。自从上次PanCamera被调用后,鼠标(或手指)已经移动的距离,像之前的帧。接下来,一个move Vector3被创建获取偏移量的x,z坐标(没有y轴上的移动)并乘以PanSpeed。接下来,我们用transform.Translate移动到照相机的世界坐标。一旦被执行,照相机实际被移动。但是,我们需要确保照相机保持在边界内,因此我们获取照相机的位置做参考并固定(Clamp)x,z坐标在合适的边界内。比如,如果我们移动x轴到更低值BondsX[0].我们用BoundsX[0]来替代它确保不会向左走得更多,同样确保上限不会走得更远。相同的逻辑被用在z轴上。因为没有y轴上的移动,我们不需要担心这个。这个固定的位置被直接用在照相机的变化,我们设置了最终的照相机的位置。剩下需要做的是抓取在lastPanPosition的newPanPosition变量被使用在下一个平移,我们全部设置。对于放大照相机,我们有ZoomCamera函数,有偏移(offsret)和速度(speed)。我们有速度参数的理由是鼠标和触摸控制放大是很大不同的,每个用不同的速度。当从HandleMouse调用ZoomCamera时,你看到我们提供ZoomSpeedMouse常量。这个方法比PanCamera更简单因为我们只需要修改一个简单的属性,是照相机的视场角。视场角的定义是照相机能看到多少度。更有用的是什么,正如你在unity编辑器中实验得到的通过拖动照相机的fieldofview滑条,是更低的fileofview意味着照相机能看到更少垂直方向的,所以会移动的更近。相反,fieldofview越高,照相机离得越远。正如下面的GIF图片所示,效果很强大,但照相机绝不是真的在动。不管怎样,我们简单固定fieldOfView一个新的值,这个新值是,如果新的值超出边界值,目前的fieldofView减去偏移量乘以速度或者低于或高于放大的边界得到的。对了,这一点你应该准备在unity编辑器中测试鼠标控制。运行游戏并点击并拖动来移动照相机,滚动滑轮来放大缩小照相机,修改顶部的常量来适应你们的需要。处理触摸 最后我们将拓展触摸控制。我最后保存这,个因为很难测试。因为你需要一个真正的设备来测试,需要整个应用构造并导致一个更慢的进程。因为我们知道放大缩小能很好作用于桌面,我们假设我们已经开发严密的逻辑来拓展触摸,不会犯很多错。来看下函数:void HandleTouch() {switch(Input.touchCount) {case 1: // PanningwasZoomingLastFrame =// If the touch began, capture its position and its finger ID.// Otherwise, if the finger ID of the touch doesn't match, skip it.Touch touch = Input.GetTouch(0);if (touch.phase == TouchPhase.Began) {lastPanPosition = touch.panFingerId = touch.fingerId;} else if (touch.fingerId == panFingerId && touch.phase == TouchPhase.Moved) {PanCamera(touch.position);}case 2: // ZoomingVector2[] newPositions = new Vector2[]{Input.GetTouch(0).position, Input.GetTouch(1).position};if (!wasZoomingLastFrame) {lastZoomPositions = newPwasZoomingLastFrame =} else {// Zoom based on the distance between the new positions compared to the// distance between the previous positions.float newDistance = Vector2.Distance(newPositions[0], newPositions[1]);float oldDistance = Vector2.Distance(lastZoomPositions[0], lastZoomPositions[1]);float offset = newDistance - oldDZoomCamera(offset, ZoomSpeedTouch);lastZoomPositions = newP}default:wasZoomingLastFrame =}}这个函数基于触摸屏幕的手指可以分为两部分。如果仅仅单个手指触摸,我们处理缩小。如果是两个手指触摸,我们处理放大。我们先拆解下缩小的逻辑,然后再拆解放大逻辑。对于缩小,我们首先设置wasZoomingLastFrame布尔变量为false,我们很快会变回原值。接下来,我们会检查单个Touch的状态并执行。如果开始这个帧触摸,当手指移动的时候,我们存储位置和手指ID用在连续的帧。说到这个,我们接下来检测是否现在的单个触摸手指匹配用来缩小照相机的手指。如果可以移动,我们调用PanCamera,传递手指的位置。接下来放大的部分(这里是两个手指),我们在vector2[]中存储两个手指的位置叫做newPositions.如果我们在最后一帧期间不放大,在lastZoomPositions数组中存储newPositions数组,并设置wasZoomingLastFrame为真。如果你调用我们的设置为假,当我们缩小。因此当有两个手指在屏幕的时候,我们知道开始放大。如果我们在最后一帧放大,我们计算当前帧的手指之间的距离以及前一帧的手指之间的距离,基于两个距离之间的offset,告诉我们手指的指向的移动(它们会变得更亲近或更疏远)。我们为ZoomSpeedTouch提供oofset与ZoomCamera,处理fieldofView变化。最终,我们缓存在lastZoomPositions的变量newPositions,我们做放大的逻辑。最终在default例子中,意味着有0个手指或多余两个手指在屏幕上,我们简单设置wasZoomingLastFrame为假。然后在一个触摸设备上运行游戏(Android,iphone,ipad)你应该发现,以熟悉的很时尚的方法,你可以通过拖动你的手指来缩小照相机或者放大。全部资源 正如我们开始说的,这是CameraHandler脚本的全部代码。把这个脚本插入到Unity3d项目中,附加到你的照相机,并调整边界和速度来适合你的需要。using UnityEusing System.Cpublic class CameraHandler : MonoBehaviour {private static readonly float PanSpeed = 20f;private static readonly float ZoomSpeedTouch = 0.1f;private static readonly float ZoomSpeedMouse = 0.5f;private static readonly float[] BoundsX = new float[]{-10f, 5f};private static readonly float[] BoundsZ = new float[]{-18f, -4f};private static readonly float[] ZoomBounds = new float[]{10f, 85f};private Cprivate Vector3 lastPanPprivate int panFingerId; // Touch mode onlyprivate bool wasZoomingLastF // Touch mode onlyprivate Vector2[] lastZoomP // Touch mode onlyvoid Awake() {cam = GetComponent();}void Update() {if (Input.touchSupported && Application.platform != RuntimePlatform.WebGLPlayer) {HandleTouch();} else {HandleMouse();}}void HandleTouch() {switch(Input.touchCount) {case 1: // PanningwasZoomingLastFrame =// If the touch began, capture its position and its finger ID.// Otherwise, if the finger ID of the touch doesn't match, skip it.Touch touch = Input.GetTouch(0);if (touch.phase == TouchPhase.Began) {lastPanPosition = touch.panFingerId = touch.fingerId;} else if (touch.fingerId == panFingerId && touch.phase == TouchPhase.Moved) {PanCamera(touch.position);}case 2: // ZoomingVector2[] newPositions = new Vector2[]{Input.GetTouch(0).position, Input.GetTouch(1).position};if (!wasZoomingLastFrame) {lastZoomPositions = newPwasZoomingLastFrame =} else {// Zoom based on the distance between the new positions compared to the// distance between the previous positions.float newDistance = Vector2.Distance(newPositions[0], newPositions[1]);float oldDistance = Vector2.Distance(lastZoomPositions[0], lastZoomPositions[1]);float offset = newDistance - oldDZoomCamera(offset, ZoomSpeedTouch);lastZoomPositions = newP}default:wasZoomingLastFrame =}}void HandleMouse() {// On mouse down, capture it's position.// Otherwise, if the mouse is still down, pan the camera.if (Input.GetMouseButtonDown(0)) {lastPanPosition = Input.mouseP} else if (Input.GetMouseButton(0)) {PanCamera(Input.mousePosition);}// Check for scrolling to zoom the camerafloat scroll = Input.GetAxis("Mouse ScrollWheel");ZoomCamera(scroll, ZoomSpeedMouse);}void PanCamera(Vector3 newPanPosition) {// Determine how much to move the cameraVector3 offset = cam.ScreenToViewportPoint(lastPanPosition - ewPanPosition);Vector3 move = new Vector3(offset.x * PanSpeed, 0, offset.y * PanSpeed);// Perform the movementtransform.Translate(move, Space.World);// Ensure the camera remains within bounds.Vector3 pos = transform.pos.x = Mathf.Clamp(transform.position.x, BoundsX[0], BoundsX[1]);pos.z = Mathf.Clamp(transform.position.z, BoundsZ[0], BoundsZ[1]);transform.position =// Cache the positionlastPanPosition = newPanP}void ZoomCamera(float offset, float speed) {if (offset == 0) {}cam.fieldOfView = Mathf.Clamp(cam.fieldOfView - (offset * speed), ZoomBounds[0], ZoomBounds[1]);}}本文转载在网络 感谢您的阅读 本文如有侵权请联系我们
Unity3D培训教程分享Unity3D 中用触摸(点击或拖动来缩小,手指捏放来放大)设备包括及iOS,以及用桌面上的鼠标(点击和拖动来缩小,鼠标滚轮来放大)及游戏的WebGL版本来缩放照相机。
unity3d培训机构为大家分享一下Unity上的Json序列化,应该一说到这个词语,我们肯定会觉得,这应该是很常用的一个功能点
对于大多数人来说,可能不知道Unity3D是什么,但是却稍微了解VR虚拟现实是什么,更不会把VR虚拟现实和Unity3D联系在一起,外行的人根本不知道这两者之间有什么关系。
在unity3d中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position,通过Transform组件移动物体
Copyright (C)
All Rights Reserved
选择城市和中心
达内北京亦庄大学生实训基地
达内北京网络营销中心
达内北京会计中心
[根据您的请求访问wap站点,不代表本站赞成以上的内容或立场]
haodewap.net相机照相以及处理图片的压缩
我们知道在app处理图片是经常会出现oom,原因就是我们在处理图片的时候图片所占的内存太大导致的,这里就介绍怎么去结局图片占内存过大的方法,当然,也是为了自己以后使用能方便些。
这篇文章也是在网上看了很多大牛的文章之后自己整理出来的,希望有错的地方大家提出来,一起学习一起进步。
首先我们介绍下相机的使用:
大致有三种:
2. 获得原始的拍照文件
3. 获取Gallery里面的图片
第一种: 缩略图
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
第二种:获得原始的拍照文件
public void OriginalImageView(View view) {
File file = createImageFile();
outputFileUri = Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 2);
第三种:获取Gallery里面的图片
public void GalleryImageView(View view) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(&image/*&);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, 3);
上面只是简单介绍照相,下面是所有的代码:
public class MainActivity extends AppCompatActivity {
private ImageV
private Uri outputFileU
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageview = (ImageView) findViewById(R.id.imageview);
public void PriviewImageView(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
* 获得原始的拍照文件
public void OriginalImageView(View view) {
File file = createImageFile();
outputFileUri = Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 2);
* 获取Gallery里面的图片
public void GalleryImageView(View view) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(&image/*&);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, 3);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != RESULT_OK) {
if (requestCode == 1) {/**缩略图*/
Bitmap bitmap = data.getExtras().getParcelable(&data&);
imageview.setImageBitmap(bitmap);
} else if (requestCode == 2) { /**获得原始的拍照文件*/
Toast.makeText(MainActivity.this, &成功&, Toast.LENGTH_SHORT).show();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), outputFileUri);
imageview.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
} else if (requestCode == 3) {/**获取Gallery里面的图片*/
Toast.makeText(MainActivity.this, data.getData().toString(), Toast.LENGTH_SHORT).show();
getRealPathFromURI(data.getData());/**获取图片真实路径*/
public static File createImageFile() {
String timeStamp = new SimpleDateFormat(&yyyyMMdd_HHmmss&).format(new Date());
String imageFileName = &JPEG_& + timeStamp + &_&;
File image = File.createTempFile(imageFileName, &.jpg&, Environment.getExternalStorageDirectory());
} catch (IOException e) {
private String getRealPathFromURI(Uri contentURI) {
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) {
result = contentURI.getPath();
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
其次,在处理图片之前,我们应该了解BitMap和BitmapFactory的一些常用方法,在这里我简单介绍几种常用的。
1.计算图片像素的方法是 bitmap.getWidth()和bitmap.getHeight();
2.bitmap.getByteCount() 是计算它的像素所占用的内存,(bitmap.getWidth()*bitmap.getHeight()*4=bitmap.getByteCount());
3.pressFormat.JPEG, 100, os),第一个参数是图片的类型,第二个参数是指图片质量(设置为30时是指图片质量被压缩了百分之70,最大100,最小0),第三个参数是指图片流。
BitmapFactory:
1.BitmapFactory.Options使用这个对象去处理图片的属性;
2.inJustDecodeBounds如果是true的话只会返回图片的宽和高;
3.inSampleSize是指设置缩放比例,设置为2时变为原来的1/2(这里的1/2值得是宽和高分别是原图的1/2,所以图片是被压缩了4倍);
4.BitmapFactory.decodeFile(path,options),这个方法的path是图片的路径,options就是BitmapFactory.Options的对象。
5.BitmapFactory.decodeFile(path),返回的是这个路径下图片的B
6.BitmapFactory.decodeStream(is, null, options),这个方法is是图片的流,null 是指位图,我们可以设置为nullm,options就是BitmapFactory.Options的对象。
7.BitmapFactory.decodeStream(is),将is转化为BitMap对象;
图片压缩有两种方法,一种是质量压缩((不改变图片的尺寸)),一种是尺寸压缩(像素上的压缩也成采样率压缩)。
测试图片在压缩前和压缩后的大小:
FileInputStream fs = new FileInputStream(pathName);
System.out.println(&图片的大小==&+fs.available());
测试图片所占内存大小:
Bitmap bm = BitmapFactory.decodeFile(pathName);;
System.out.println(&内存的大小==&+bm.getByteCount());
System.out.println(&内存大小的另一种求法==&+bm.getWidth() * bm.getHeight()*4 );
质量压缩不会减少图片对内存的使用,但是开发app的程序员都知道我们会尽量为用户减少流量,或者将图片保存到本地时进行压缩,所以使用质量压缩会减少图片的大小,这样上传图片时速度快(因为图片变小了),用户体验就会好。
下面就是方法:
FileInputStream fs = new FileInputStream(pathName);
System.out.println(&图片压缩前的大小==&+fs.available());
public static Bitmap CompressBitmap(Bitmap bitmap){
System.out.println(&质量压缩前内存=&+bitmap.getByteCount());
ByteArrayOutputStream bo=new
ByteArrayOutputStream();
//通过这里改变压缩类型,其有不同的结果
pressFormat.JPEG, 70, bo); //注意:不要讲jpg格式的图片压缩成png格式的图片,如果设置成png的话图片可能会变大,但是内存不会发生变化
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
System.out.println(&图片压缩后的大小=&+bi.available());
bitmap=BitmapFactory.decodeStream(bis);
System.out.println(&质量压缩后内存=&+bitmap.getByteCount());
通过实现我们得出图片压缩前和压缩后的大小确实变了,压缩后的比压缩前的小,但是图片的内存使用没有变。
但是,它不会减少图片的像素。它是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的。进过它压缩的图片文件大小会有改变,但是导入成bitmap后占得内存是不变的。因为要保持像素不变,所以它就无法无限压缩,到达一个值之后就不会继续变小了。显然这个方法并不适用与缩略图,其实也不适用于想通过压缩图片减少内存的适用,仅仅适用于想在保证图片质量的同时减少文件大小的情况而已
//最开始使用这个来进行压缩,但是始终压缩不到32k这么小
public void Example(){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
  pressFormat.JPEG, 100 , baos);
  int options = 100 ;
  while ( baos.toByteArray().length / 1024 & 32 ) {
  baos.reset();
  pressFormat.JPEG, options, baos);
  options -= 10 ;
  ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
  Bitmap bitmap = BitmapFactory.decodeStream(isBm, null , null );
2.尺寸压缩(也成采样率压缩)
尺寸压缩会改变图片所占内存的大小,也就是解决我们在加载图片时有时候会出现的OOM。
第一种: 根据图片路径,下面就是方法:
public static Bitmap CompressBitmapSizePath(String imagePath){
Bitmap bitmap = BitmapFactory.decodeFile(pathName);
System.out.println(&内存压缩前==&+bitmap.getByteCount());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = //设置成true我们我是为了得到图片的宽高,这个方法返回的Bitmap对象为空,减少内存的消耗
Bitmap bitmap = BitmapFactory.decodeFile(imagePath,options);
// 这个方法返回的bitmap 为空,因为options.inJustDecodeBounds设置为true
options.inJustDecodeBounds =
options.inSampleSize = 2; //原来的1/2
bitmap = BitmapFactory.decodeFile(imagePath,options);
System.out.println(&内存压缩后==&+bitmap.getByteCount());
第二种:根据流,下面就是方法:
public static Bitmap CompressBitmapSizeIs(Context context, int resId){
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable =
opt.inInputShareable =
opt.inSampleSize = 2;
//获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is,null,opt);
第三中:根据Bitmap,以下就是方法:
public Bitmap CompressBitmapSizeBitMap(Bitmap image, float pixelW, float pixelH) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
pressFormat.JPEG, 100, os);
if( os.toByteArray().length / ) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
os.reset();//重置baos即清空baos
pressFormat.JPEG, 50, os);//这里压缩50%,把压缩后的数据存放到baos中
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds =
newOpts.inPreferredConfig = Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(is, null, newOpts);
newOpts.inJustDecodeBounds =
int w = newOpts.outW
int h = newOpts.outH
float hh = pixelH;// 设置高度为240f时,可以明显看到图片缩小了
float ww = pixelW;// 设置宽度为120f,可以明显看到图片缩小了
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w & h && w & ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w & h && h & hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
if (be &= 0) be = 1;
newOpts.inSampleSize =//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
is = new ByteArrayInputStream(os.toByteArray());
bitmap = BitmapFactory.decodeStream(is, null, newOpts);
//压缩好比例大小后再进行质量压缩
return compress(bitmap, maxSize); // 这里再进行质量压缩的意义不大,反而耗资源,删除
使用中可以根据自己的需要自己选择,最后给大家提供一个完美的压缩图片尺寸的方法,也是我在网上找到的:
//根据路径获得突破并压缩返回bitmap用于显示
public static Bitmap getSmallBitmap(String filePath,int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds =
//只返回图片的大小信息
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds =
return BitmapFactory.decodeFile(filePath, options);
//计算图片的缩放值
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outH
final int width = options.outW
int inSampleSize = 1;
if (height & reqHeight || width & reqWidth) {
final int heightRatio = Math.round((float) height/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio & widthRatio ? heightRatio : widthR
return inSampleS
最后,使用完BitMap是我们一般要:
bmp.recycle() ; //回收图片所占的内存
system.gc() //提醒及时回收 ,回收内存。
另外,一般不要不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存,以下提供一个优化方法(也就是尺寸压缩中的第二个方法,只是一个优化):
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable =
opt.inInputShareable =
opt.inSampleSize = 2;
//获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is,null,opt);

我要回帖

更多关于 unity3d 人物模型 的文章

 

随机推荐