版本:3.7.4
一、3d小地图
用RenderTexture实现Sprite版小地图和炫酷的传送门 - Creator 3.x - Cocos中文社区
按照官方论坛示例构建一个3d小地图,其实就是在人物上添加一个俯视的摄像头节点,然后将内容输出到一个Sprite上,作为内容展示,按照实际内容调整 摄像机 的Ortho Height和Near参数。
优点:很简单就可以实现,并且能保留场景原本色彩。
缺点:当人物上有模型遮挡时无法体现,还有就是因为是3d摄像机投影实现的,所以性能影响较大,以我的测试场景为例,使用后Drawcall数值增加200左右。
二、2d小地图
首先先快速制作小地图图片资源,在3d设计软件(blender)中打开建筑场景,使用俯视视角,打开透视,直接截图即可,比如如下:
小地图目录结构如下
首先创建一个Mask遮罩,mapMask就是遮罩,大小为小地图要展示的大小,给mapres的Sprite指定资源为上面的小地图,按照实际需要设置大小,比如 500*500。为了体现小地图在屏幕的范围,创建一个Sprite为board,资源是一张四周有1px 细线的透明图片,大小和mapMask一致,point为图标指针,为了清晰表示人物方向及位置。
效果如下:
创建一个ts脚本,绑定到这个预制资源的最上层节点,我的内容如下:
@ccclass('Map2dDataController')
export class Map2dDataController extends Component {
@property({ type: String, displayName: '目标对象名称' })
nodeName: string = '';
@property({ type: SpriteFrame, displayName: '2d底图资源' })
mapImage: SpriteFrame
//目标对象
person: Node = null
//当前位置,包含预设
now_2d_position = { x: -3, y: 295 }
//上一个点的位置
last_2d_position = this.now_2d_position
//上一个点的位置
last_3d_position = { x: 0, y: 0 }
//地图sprite
sp: Node = null
//自身指针
point: Node = null
//3d对象转换为2d对象倍率
vary = { x: -9.91, y: 13.57 }
start() {
if (!this.mapImage) {
return
}
this.sp = this.node.getChildByName('canvas').getChildByName('mapMask').getChildByName('mapres')
this.sp.getComponent(Sprite).spriteFrame = this.mapImage
this.point = this.node.getChildByName('canvas').getChildByName('board').getChildByName('point')
if (!this.nodeName) {
this.nodeName = RoleListUtil.getList()[0].code
}
//展示的数据
this.person = find(RoleListUtil.roleBasePath + this.nodeName)
this.sp.setPosition(new Vec3(this.now_2d_position.x, this.now_2d_position.y, 0))
this.last_3d_position = { x: this.reduceNumber(this.person.getPosition().x), y: this.reduceNumber(this.person.getPosition().z) }
}
update() {
if (this.sp) {
this.positionHandle()
}
if (this.point) {
let rota = new Vec3()
this.person.getRotation().getEulerAngles(rota)
this.point.setRotationFromEuler(new Vec3(0, 0, rota.y + 180))
}
}
positionHandle() {
let x = this.reduceNumber(this.person.getPosition().x)
let y = this.reduceNumber(this.person.getPosition().z)
/**
* 如果 3d 位置, 上一点和当前点位置相同,不执行小地图位置移动
*/
if (x == this.last_3d_position.x && y == this.last_3d_position.y) {
return
}
// 计算移动位置并赋值
this.now_2d_position = {
x: this.reduceNumber(this.last_2d_position.x + (x - this.last_3d_position.x) * this.vary.x),
y: this.reduceNumber(this.last_2d_position.y + (y - this.last_3d_position.y) * this.vary.y)
}
console.log(this.now_2d_position)
this.sp.setPosition(new Vec3(this.now_2d_position.x, this.now_2d_position.y, 0))
//记录当前2d坐标为上一点坐标
this.last_2d_position=this.now_2d_position
//记录下当前3d点坐标为上一点坐标
this.last_3d_position = { x: x, y: y }
}
reduceNumber(num: number): number {
return Number(num.toFixed(2))
}
}
这里 now_2d_position 位置为需要将人物初始化到的2d地图点,vary为3d到2d的移动倍率(需要按照实际进行计算)。
计算过程如下:
当前2d点为=当前2d点坐标+3d点移动差值*倍率
倍率获取需要调试,分别选取3d和2d的左上角和右下角的四组点,将获取的点代入上述公式计算。